maxwalksat.c

00001 /* costwalksat modified 10/24 by H. Kautz */
00002 /* costwalksat by Jiang October 94 based on the following */
00003 /* walksat by Bram Cohen 7/93 */
00004 /* Modifications by Henry Kautz 9/93 */
00005 /* This program continues to accept the old data except that*/
00006 /* it treats each clause with a default cost of unit 1*/
00007 /* Modified Wed May  8 20:47:37 PDT 2002 for -hard option */
00008 
00009 #define MAXATOM 100000          /* maximum possible number of atoms */
00010 
00011 #ifdef Huge
00012 #define STOREBLOCK 2000000      /* size of block to malloc each time */
00013 #else
00014 #define STOREBLOCK 1000000      /* size of block to malloc each time */
00015 #define MAXCLAUSE 500000        /* maximum possible number of clauses */
00016 #endif
00017 
00018 #define TRUE 1
00019 #define FALSE 0
00020 
00021 #define BIG 100000000
00022 
00023 #define MAXLENGTH 1000          /* maximum number of literals which can be in any clause */
00024 
00025 #define RANDOM 0
00026 #define PRODUCTSUM 1
00027 #define RECIPROCAL 2
00028 #define ADDITIVE 3
00029 #define BEST 4
00030 #define EXPONENTIAL 5
00031 #define TABU 6
00032 
00033 #define NOVALUE -1
00034 
00035 #define INIT_PARTIAL 1
00036 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <math.h>
00040 #include <sys/time.h>
00041 #include <sys/resource.h>
00042 #include <signal.h>
00043 
00044 /* NOTE: if the -O3 option is not available, then comment out this macro! */
00045 static int scratch;
00046 #define abs(x) ((scratch=(x))>0?scratch: -scratch)
00047 
00048 
00049         /* Atoms start at 1 */
00050         /* Not a is recorded as -1 * a */
00051         /* One dimensional arrays are statically allocated. */
00052         /* Two dimensional arrays are dynamically allocated in */
00053         /* the second dimension only.  */
00054         /* (Arrays are not entirely dynamically allocated, because */
00055         /* doing so slows execution by 25% on SGI workstations.) */
00056 
00057 
00058 int numatom;
00059 int numclause;
00060 int numliterals;
00061 
00062 #ifdef Huge
00063 int ** clause;                  /* clauses to be satisfied */
00064                                 /* indexed as clause[clause_num][literal_num] */
00065 int * cost;                     /* cost of each clause */
00066 int * size;                     /* length of each clause */
00067 int * false;                    /* clauses which are false */
00068 int * wherefalse;               /* where each clause is listed in false */
00069 int * numtruelit;               /* number of true literals in each clause */
00070 #else
00071 int * clause[MAXCLAUSE];        /* clauses to be satisfied */
00072                                 /* indexed as clause[clause_num][literal_num] */
00073 int cost[MAXCLAUSE];            /* cost of each clause */
00074 int size[MAXCLAUSE];            /* length of each clause */
00075 int false[MAXCLAUSE];           /* clauses which are false */
00076 int lowfalse[MAXCLAUSE];
00077 int wherefalse[MAXCLAUSE];      /* where each clause is listed in false */
00078 int numtruelit[MAXCLAUSE];      /* number of true literals in each clause */
00079 #endif
00080 
00081 int *occurence[2*MAXATOM+1];    /* where each literal occurs */
00082                                 /* indexed as occurence[literal+MAXATOM][occurence_num] */
00083 
00084 int numoccurence[2*MAXATOM+1];  /* number of times each literal occurs */
00085 
00086 
00087 int atom[MAXATOM+1];            /* value of each atom */ 
00088 int lowatom[MAXATOM+1];
00089 
00090 int changed[MAXATOM+1];         /* step at which atom was last flipped */
00091 
00092 int breakcost[MAXATOM+1];       /* the cost of clauses that introduces if var is flipped */
00093 
00094 int numfalse;                   /* number of false clauses */
00095 int costofnumfalse;             /* cost associated with the number of false clauses */
00096 
00097 
00098 int costexpected = FALSE;   /*indicate whether cost is expected from the input*/
00099 int abort_flag;
00100 
00101 int heuristic;                  /* heuristic to be used */
00102 int numerator;                  /* make random flip with numerator/denominator frequency */
00103 int denominator;                
00104 int tabu_length;                /* length of tabu list */
00105 
00106 long int numflip;               /* number of changes so far */
00107 long int numnullflip;           /*  number of times a clause was picked, but no  */
00108                                 /*  variable from it was flipped  */
00109 
00110 int highestcost=1;               /*The highest cost of a clause violation*/
00111 int eqhighest=0;        /*Is there a clause violated with the highest cost*/
00112 int numhighest=0;      /*Number of violated clauses with the highest cost*/
00113 
00114 int hard=0; /* if true never break a highest cost clause */
00115 
00116 int selecthigh(int);   /*find the int'th clause with the highest cost*/
00117 
00118 double elapsed_seconds(void);
00119 int countunsat(void);
00120 void countlowunsatcost( int *, int *);
00121 void scanone(int argc, char *argv[], int i, int *varptr);
00122 void init(char initfile[], int initoptions);
00123 void initprob(void);                 /* create a new problem */
00124 void fix(int tofix);                 /* changes an atom to make the given clause true */
00125 void flipatom(int toflip);           /* changes the assignment of the given literal */
00126 int pickzero(int *numbreak,int clausesize);     /* return a randomly chosen zero */
00127                                                 /* if none exists, return NOVALUE */
00128 int pickweight(int *weight,int clausesize);     /* picks a number based */
00129                                                 /* on the given weights */
00130 void print_false_clauses_cost(long int lowbad);
00131 void print_low_assign(long int lowbad);
00132 void save_low_assign(void);
00133 
00134 int pickrandom(int *numbreak,int clausesize, int tofix);
00135 int pickproductsum(int *numbreak,int clausesize, int tofix);
00136 int pickreciprocal(int *numbreak,int clausesize, int tofix);
00137 int pickadditive(int *numbreak,int clausesize, int tofix);
00138 int pickbest(int *numbreak,int clausesize, int tofix);
00139 int pickexponential(int *numbreak,int clausesize, int tofix);
00140 int pickfair(int *numbreak,int clausesize, int tofix);
00141 int picktabu(int *numbreak,int clausesize, int tofix);
00142 
00143 void handle_interrupt(int sig);
00144 
00145 long super(int i);
00146 
00147 int main(int argc,char *argv[])
00148 {
00149     int i;                      /* loop counter */
00150     int j;                      /* another loop counter */
00151     int k;                      /* yet another loop counter */
00152     char initfile[100] = { 0 };
00153     int numrun = 10;
00154     int cutoff = 100000;
00155     int base_cutoff = 100000;
00156     int printonlysol = FALSE;
00157     int printsolcnf = FALSE;
00158     int printfalse = FALSE;
00159     int printlow = FALSE;
00160     int initoptions = FALSE;
00161     int superlinear = FALSE;
00162     int printtrace = FALSE;
00163     long int totalflip = 0;     /* total number of flips in all tries so far */
00164     long int totalsuccessflip = 0; /* total number of flips in all tries which succeeded so far */
00165     int numtry = 0;             /* total attempts at solutions */
00166     int numsuccesstry = 0;      /* total found solutions */
00167     int numsol = 1;             /* stop after this many tries succeeds */
00168     int tochange;
00169     int seed;                   /* seed for random */
00170     struct timeval tv;
00171     struct timezone tzp;
00172     double expertime;
00173     long flips_this_solution;
00174     long int lowbad;            /* lowest number of bad clauses during try */
00175     long int lowcost;           /* lowest cost of bad clauses during try */
00176     int targetcost = 0;         /* the cost at which the program terminates*/
00177     long x;
00178     long integer_sum_x = 0;
00179     double sum_x = 0.0;
00180     double sum_x_squared = 0.0;
00181     double mean_x;
00182     double second_moment_x;
00183     double variance_x;
00184     double std_dev_x;
00185     double std_error_mean_x;
00186     double seconds_per_flip;
00187     int r;
00188     int sum_r = 0;
00189     double sum_r_squared = 0.0;
00190     double mean_r;
00191     double variance_r;
00192     double std_dev_r;
00193     double std_error_mean_r;
00194     int worst_cost, computed_cost;
00195 
00196     gettimeofday(&tv,&tzp);
00197     seed = (( tv.tv_sec & 0177 ) * 1000000) + tv.tv_usec;
00198     heuristic = BEST;
00199     numerator = NOVALUE;
00200     denominator = 100;
00201 
00202     for (i=1;i < argc;i++)
00203       {
00204           if (strcmp(argv[i],"-withcost") == 0)
00205             costexpected = TRUE;
00206           else if (strcmp(argv[i],"-seed") == 0)
00207             scanone(argc,argv,++i,&seed);
00208           else if (strcmp(argv[i],"-targetcost") == 0)
00209             scanone(argc,argv,++i,&targetcost);
00210           else if (strcmp(argv[i],"-cutoff") == 0)
00211             scanone(argc,argv,++i,&cutoff);
00212           else if (strcmp(argv[i],"-random") == 0)
00213             heuristic = RANDOM;
00214           else if (strcmp(argv[i],"-productsum") == 0)
00215             heuristic = PRODUCTSUM;
00216           else if (strcmp(argv[i],"-reciprocal") == 0)
00217             heuristic = RECIPROCAL;
00218           else if (strcmp(argv[i],"-additive") == 0)
00219             heuristic = ADDITIVE;
00220           else if (strcmp(argv[i],"-exponential") == 0)
00221             heuristic = EXPONENTIAL;
00222           else if (strcmp(argv[i],"-best") == 0)
00223             heuristic = BEST;
00224           else if (strcmp(argv[i],"-noise") == 0)
00225             {
00226                 scanone(argc,argv,++i,&numerator);
00227                 scanone(argc,argv,++i,&denominator);
00228             }
00229           else if (strcmp(argv[i],"-init") == 0  && i < argc-1)
00230             sscanf(argv[++i], " %s", initfile);
00231           else if (strcmp(argv[i],"-partial") == 0)
00232             initoptions = INIT_PARTIAL;
00233           else if (strcmp(argv[i],"-super") == 0)
00234             superlinear = TRUE;
00235           else if (strcmp(argv[i],"-tries") == 0)
00236             scanone(argc,argv,++i,&numrun);
00237           else if (strcmp(argv[i],"-tabu") == 0)
00238             {
00239                 scanone(argc,argv,++i,&tabu_length);
00240                 heuristic = TABU;
00241             }
00242           else if (strcmp(argv[i],"-low") == 0)
00243             printlow = TRUE;
00244           else if (strcmp(argv[i],"-sol") == 0)
00245             {
00246                 printonlysol = TRUE;
00247                 printlow = TRUE;
00248             }
00249           else if (strcmp(argv[i],"-bad") == 0)
00250             printfalse = TRUE;
00251           else if (strcmp(argv[i],"-hard") == 0)
00252             hard = TRUE;
00253           else if (strcmp(argv[i],"-numsol") == 0)
00254             scanone(argc,argv,++i,&numsol);
00255           else if (strcmp(argv[i],"-trace") == 0)
00256             scanone(argc,argv,++i,&printtrace);
00257           else 
00258             {
00259                 fprintf(stderr, "Bad argument %s\n", argv[i]);
00260                 fprintf(stderr, "General parameters:\n");
00261                 fprintf(stderr, "  -seed N -cutoff N -tries N\n");
00262                 fprintf(stderr, "  -numsol N = stop after finding N solutions\n");
00263                 fprintf(stderr, "  -init FILE = set vars not included in FILE to false\n");
00264                 fprintf(stderr, "  -partial FILE = set vars not included in FILE randomly\n");
00265                 fprintf(stderr, "  -withcost = input is a set of weighted clauses\n");
00266                 fprintf(stderr, "  -targetcost N = find assignments of cost <= N (MAXSAT)\n");
00267                 fprintf(stderr, "  -hard = never break a highest-cost clause\n");
00268                 fprintf(stderr, "Heuristics:\n");
00269                 fprintf(stderr, "  -noise N M -best -super -tabu N\n");
00270                 fprintf(stderr, "  -productsum -reciprocal -additive -exponential\n");
00271                 fprintf(stderr, "Printing:\n");
00272                 fprintf(stderr, "  -trace N = print statistics every N flips\n");
00273                 fprintf(stderr, "  -sol = print assignments where cost < target\n");
00274                 fprintf(stderr, "  -low = print lowest assignment each try\n");
00275                 fprintf(stderr, "  -bad = print unsat clauses each try\n");
00276                 fprintf(stderr, "  -solcnf = print sat assign in cnf format, and exit\n");
00277                 exit(-1);
00278             }
00279       }
00280     base_cutoff = cutoff;
00281     if (numerator==NOVALUE){
00282         if (heuristic==BEST)
00283           numerator = 50;
00284         else
00285           numerator = 0;
00286     }
00287 
00288     srandom(seed);
00289 #ifdef Huge
00290     printf("maxwalksat version 20 (Huge)\n");
00291 #else
00292     printf("maxwalksat version 20\n");
00293 #endif
00294     printf("seed = %i\n",seed);
00295     printf("cutoff = %i\n",cutoff);
00296     printf("tries = %i\n",numrun);
00297     printf("numsol = %i\n",numsol);
00298     printf("targetcost = %i\n",targetcost);
00299 
00300     printf("heuristic = ");
00301 
00302     switch(heuristic)
00303       {
00304         case RANDOM:
00305           printf("random");
00306           break;
00307         case PRODUCTSUM:
00308           printf("productsum");
00309           break;
00310         case RECIPROCAL:
00311           printf("reciprocal");
00312           break;
00313         case ADDITIVE:
00314           printf("additive");
00315           break;
00316         case BEST:
00317           printf("best");
00318           break;
00319         case EXPONENTIAL:
00320           printf("exponential");
00321           break;
00322         case TABU:
00323           printf("tabu %d", tabu_length);
00324           break;
00325       }
00326     if (numerator>0){
00327         printf(", noise %d / %d", numerator, denominator);
00328     }
00329     if (superlinear)
00330       printf(", super");
00331     if (printtrace)
00332       printf(", trace %d", printtrace);
00333     if (initfile[0]){
00334         printf(", init %s", initfile);
00335         if (initoptions == INIT_PARTIAL)
00336           printf(", partial");
00337     }
00338     printf("\n");
00339     
00340     initprob();
00341 
00342     if (costexpected) printf("clauses contain explicit costs\n");
00343     else printf("clauses all assigned default cost of 1\n");
00344 
00345     printf("numatom = %i, numclause = %i, numliterals = %i\n",numatom,numclause,numliterals);
00346     printf("wff read in\n");
00347     printf("                                           average             average       mean              standard\n");
00348     printf("    lowest     worst    number                when                over      flips                 error\n");
00349     printf("      cost    clause    #unsat    #flips     model   success       all      until        std         of\n");
00350     printf("  this try  this try  this try  this try     found      rate     tries     assign        dev       mean\n");
00351 
00352     signal(SIGINT, (void *) handle_interrupt);
00353     abort_flag = FALSE;
00354     numnullflip = 0;
00355     (void) elapsed_seconds();
00356     x = 0; r = 0;
00357     lowcost = BIG;
00358     for(k = 0;k < numrun;k++)
00359       {
00360           init(initfile, initoptions);
00361           lowbad = numfalse; 
00362           lowcost = costofnumfalse;
00363           save_low_assign();
00364           numflip = 0;
00365 
00366           if (superlinear) cutoff = base_cutoff * super(r+1);
00367 
00368           while((numflip < cutoff) && (costofnumfalse > targetcost))
00369             {
00370                 if (printtrace && (numflip % printtrace == 0)){
00371                     printf("%10i          %10i%10li\n", costofnumfalse,numfalse,numflip);
00372                     fflush(stdout);
00373                 }
00374                 numflip++;
00375                 if ((eqhighest) && (highestcost!=1))
00376                 {/* fprintf(stderr, "number of highest %i\n", numhighest);*/    
00377                         fix(selecthigh(1+random()%numhighest));
00378                 }
00379                 else fix(false[random()%numfalse]);
00380                 if (costofnumfalse < lowcost)
00381                 {
00382                     lowcost = costofnumfalse;
00383                     lowbad = numfalse;
00384                     save_low_assign();
00385                 }
00386             }
00387           numtry++;
00388           totalflip += numflip;
00389           x += numflip;
00390           r ++;
00391           if(costofnumfalse<=targetcost)
00392             {
00393                 numsuccesstry++;
00394                 totalsuccessflip += numflip;
00395                 integer_sum_x += x;
00396                 sum_x = (double) integer_sum_x;
00397                 sum_x_squared += ((double)x)*((double)x);
00398                 mean_x = sum_x / numsuccesstry;
00399                 if (numsuccesstry > 1){
00400                     second_moment_x = sum_x_squared / numsuccesstry;
00401                     variance_x = second_moment_x - (mean_x * mean_x);
00402                     /* Adjustment for small small sample size */
00403                     variance_x = (variance_x * numsuccesstry)/(numsuccesstry - 1);
00404                     std_dev_x = sqrt(variance_x);
00405                     std_error_mean_x = std_dev_x / sqrt((double)numsuccesstry);
00406                 }
00407                 sum_r += r;
00408                 mean_r = ((double)sum_r)/numsuccesstry;
00409                 sum_r_squared += ((double)r)*((double)r);
00410                 x = 0;
00411                 r = 0;
00412             }
00413 
00414           countlowunsatcost(&computed_cost, &worst_cost);
00415           if(lowcost != computed_cost)
00416             {
00417                 fprintf(stderr, "Program error, verification of assignment cost fails!\n");
00418                 exit(-1);
00419             }
00420 
00421           if(numsuccesstry == 0)
00422             printf("%10i%10i%10i%10li         *         0         *          *          *          *\n",
00423                    lowcost,worst_cost,lowbad,numflip);
00424           else if (numsuccesstry == 1)
00425             printf("%10i%10i%10i%10li%10li%10i%10li %10.1f          *          *\n",
00426                    lowcost,worst_cost,lowbad,numflip,totalsuccessflip/numsuccesstry,
00427                    (numsuccesstry*100)/numtry,totalflip/numsuccesstry,
00428                    mean_x);
00429           else
00430             printf("%10i%10i%10i%10li%10li%10i%10li %10.1f %10.1f %10.1f\n",
00431                    lowcost,worst_cost,lowbad,numflip,totalsuccessflip/numsuccesstry,
00432                    (numsuccesstry*100)/numtry,totalflip/numsuccesstry,
00433                    mean_x, std_dev_x, std_error_mean_x);
00434           if (numfalse>0 && printfalse)
00435             print_false_clauses_cost(lowbad);
00436           if (printlow && (!printonlysol || costofnumfalse<=targetcost))
00437             print_low_assign(lowcost);
00438 
00439           if (numsuccesstry >= numsol) break;
00440           if (abort_flag) break;
00441           fflush(stdout);
00442       }
00443     expertime = elapsed_seconds();
00444     seconds_per_flip = expertime / totalflip;
00445     printf("\ntotal elapsed seconds = %f\n", expertime);
00446     printf("average flips per second = %d\n", (long)(totalflip/expertime));
00447     if (heuristic == TABU)
00448       printf("proportion null flips = %f\n", ((double)numnullflip)/totalflip);
00449     printf("number of solutions found = %d\n", numsuccesstry);
00450     if (numsuccesstry > 0)
00451       {
00452           printf("mean flips until assign = %f\n", mean_x);
00453           if (numsuccesstry>1){
00454               printf("  variance = %f\n", variance_x);
00455               printf("  standard deviation = %f\n", std_dev_x);
00456               printf("  standard error of mean = %f\n", std_error_mean_x);
00457           }
00458           printf("mean seconds until assign = %f\n", mean_x * seconds_per_flip);
00459           if (numsuccesstry>1){
00460               printf("  variance = %f\n", variance_x * seconds_per_flip * seconds_per_flip);
00461               printf("  standard deviation = %f\n", std_dev_x * seconds_per_flip);
00462               printf("  standard error of mean = %f\n", std_error_mean_x * seconds_per_flip);
00463           }
00464           printf("mean restarts until assign = %f\n", mean_r);
00465           if (numsuccesstry>1){
00466               variance_r = (sum_r_squared / numsuccesstry) - (mean_r * mean_r);
00467               variance_r = (variance_r * numsuccesstry)/(numsuccesstry - 1);       
00468               std_dev_r = sqrt(variance_r);
00469               std_error_mean_r = std_dev_r / sqrt((double)numsuccesstry);
00470               printf("  variance = %f\n", variance_r);
00471               printf("  standard deviation = %f\n", std_dev_r);
00472               printf("  standard error of mean = %f\n", std_error_mean_r);
00473           }
00474       }
00475 
00476     if (numsuccesstry > 0)
00477       {
00478           printf("ASSIGNMENT ACHIEVING TARGET %i FOUND\n", targetcost);
00479           if(printsolcnf == TRUE)
00480             for(i = 1;i < numatom+1;i++)
00481               printf("v %i\n", atom[i] == 1 ? i : -i);
00482       }
00483     else
00484       printf("ASSIGNMENT NOT FOUND\n");
00485     return 0;
00486 }
00487 
00488 long super(int i)
00489 {
00490     long power;
00491     int k;
00492 
00493     if (i<=0){
00494         fprintf(stderr, "bad argument super(%d)\n", i);
00495         exit(1);
00496     }
00497     /* let 2^k be the least power of 2 >= (i+1) */
00498     k = 1;
00499     power = 2;
00500     while (power < (i+1)){
00501         k += 1;
00502         power *= 2;
00503     }
00504     if (power == (i+1)) return (power/2);
00505     return (super(i - (power/2) + 1));
00506 }
00507 
00508 void handle_interrupt(int sig)
00509 {
00510     if (abort_flag) exit(-1);
00511     abort_flag = TRUE;
00512 }
00513 
00514 void scanone(int argc, char *argv[], int i, int *varptr)
00515 {
00516     if (i>=argc || sscanf(argv[i],"%i",varptr)!=1){
00517         fprintf(stderr, "Bad argument %s\n", i<argc ? argv[i] : argv[argc-1]);
00518         exit(-1);
00519     }
00520 }
00521 
00522 void init(char initfile[], int initoptions)
00523 {
00524     int i;                      /* loop counter */
00525     int j;                      /* another loop counter */
00526     int thetruelit;
00527     FILE * infile;
00528     int lit;
00529 
00530     for(i = 0;i < numclause;i++)
00531       numtruelit[i] = 0;
00532     numfalse = 0;
00533     costofnumfalse = 0;
00534     eqhighest = 0;
00535     numhighest = 0;
00536 
00537     for(i = 1;i < numatom+1;i++)
00538       {
00539           changed[i] = -BIG;
00540           breakcost[i] = 0;
00541       }
00542 
00543     if (initfile[0] && initoptions!=INIT_PARTIAL){
00544         for(i = 1;i < numatom+1;i++)
00545           atom[i] = 0;
00546     }
00547     else {
00548         for(i = 1;i < numatom+1;i++)
00549           atom[i] = random()%2;
00550     }
00551 
00552     if (initfile[0]){
00553         if ((infile = fopen(initfile, "r")) == NULL){
00554             fprintf(stderr, "Cannot open %s\n", initfile);
00555             exit(1);
00556         }
00557         i=0;
00558         while (fscanf(infile, " %d", &lit)==1){
00559             i++;
00560             if (abs(lit)>numatom){
00561                 fprintf(stderr, "Bad init file %s\n", initfile);
00562                 exit(1);
00563             }
00564             if (lit<0) atom[-lit]=0;
00565             else atom[lit]=1;
00566         }
00567         if (i==0){
00568             fprintf(stderr, "Bad init file %s\n", initfile);
00569             exit(1);
00570         }
00571         close(infile);
00572         /* printf("read %d values\n", i); */
00573     }
00574 
00575     /* Initialize breakcost in the following: */
00576     for(i = 0;i < numclause;i++)
00577       {
00578           for(j = 0;j < size[i];j++)
00579             {
00580                 if((clause[i][j] > 0) == atom[abs(clause[i][j])])
00581                   {
00582                       numtruelit[i]++;
00583                       thetruelit = clause[i][j];
00584                   }
00585             }
00586           if(numtruelit[i] == 0)
00587             {
00588                 wherefalse[i] = numfalse;
00589                 false[numfalse] = i;
00590                 numfalse++;
00591                 costofnumfalse += cost[i];
00592                 if (highestcost == cost[i])
00593                 {eqhighest = 1; numhighest++;}
00594             }
00595           else if (numtruelit[i] == 1)
00596             {
00597                 breakcost[abs(thetruelit)] += cost[i];
00598             }
00599       }
00600 }
00601 
00602 void
00603 print_false_clauses_cost(long int lowbad)
00604 {
00605     int i, j;
00606     int bad;
00607     int lit, sign;
00608 
00609     printf("Unsatisfied clauses:\n");
00610     for (i=0; i<numclause; i++){
00611         bad = TRUE;
00612         for (j=0; j < size[i]; j++) {
00613             lit = clause[i][j];
00614             sign = lit > 0 ? 1 : 0;
00615             if ( lowatom[abs(lit)] == sign ){
00616                 bad = FALSE;
00617                 break;
00618             }
00619         }
00620         if (bad){
00621             printf("Cost %i ", cost[i]);
00622             for (j=0; j<size[i]; j++){
00623                 printf("%d ", clause[i][j]);
00624             }
00625             printf("0\n");
00626         }
00627     }
00628     printf("End unsatisfied clauses\n");
00629 }
00630 
00631 
00632 void initprob(void)
00633 {
00634     int i;                      /* loop counter */
00635     int j;                      /* another loop counter */
00636     int lastc;
00637     int nextc;
00638     int *storeptr;
00639     int freestore;
00640     int lit;
00641     char buf[512];
00642 
00643     while ((lastc = getchar()) == 'c')
00644       {
00645           while ((nextc = getchar()) != EOF && nextc != '\n');
00646       }
00647     ungetc(lastc,stdin);
00648     fgets(buf, 512, stdin);
00649     if (sscanf(buf, "p wcnf %i %i",&numatom,&numclause) == 2){
00650         costexpected = 1; }
00651     else if (sscanf(buf, "p cnf %i %i",&numatom,&numclause) != 2){
00652           fprintf(stderr,"Bad input file\n");
00653           exit(-1);}
00654     if(numatom > MAXATOM)
00655       {
00656           fprintf(stderr,"ERROR - too many atoms\n");
00657           exit(-1);
00658       }
00659 
00660 #ifdef Huge
00661     clause = (int **) malloc(sizeof(int *)*(numclause+1));
00662     cost = (int *) malloc(sizeof(int)*(numclause+1));
00663     size = (int *) malloc(sizeof(int)*(numclause+1));
00664     false = (int *) malloc(sizeof(int)*(numclause+1));
00665     lowfalse = (int *) malloc(sizeof(int)*(numclause+1));
00666     wherefalse = (int *) malloc(sizeof(int)*(numclause+1));
00667     numtruelit = (int *) malloc(sizeof(int)*(numclause+1));
00668 #else
00669     if(numclause > MAXCLAUSE)                     
00670       {                                      
00671           fprintf(stderr,"ERROR - too many clauses\n"); 
00672           exit(-1);                              
00673       }                                        
00674 #endif
00675     freestore = 0;
00676     numliterals = 0;
00677     for(i = 0;i < 2*MAXATOM+1;i++)
00678       numoccurence[i] = 0;
00679     for(i = 0;i < numclause;i++)
00680       {
00681           if (costexpected) 
00682             {
00683              if (scanf("%i ",&cost[i]) != 1)
00684                   {
00685                       fprintf(stderr, "Bad input file\n");
00686                       exit(-1);
00687                   }
00688              else if (cost[i]>highestcost) highestcost = cost[i];
00689             }
00690           else cost[i] = 1; /*the default cost of a clause violation is unit 1*/
00691 
00692           size[i] = -1;
00693           if (freestore < MAXLENGTH)
00694             {
00695                 storeptr = (int *) malloc( sizeof(int) * STOREBLOCK );
00696                 freestore = STOREBLOCK;
00697                 fprintf(stderr,"allocating memory...\n");
00698             }
00699           clause[i] = storeptr;
00700           do
00701             {
00702                 size[i]++;
00703                 if(size[i] > MAXLENGTH)
00704                   {
00705                       printf("ERROR - clause too long\n");
00706                       exit(-1);
00707                   }
00708                 if (scanf("%i ",&lit) != 1)
00709                   {
00710                       fprintf(stderr, "Bad input file\n");
00711                       exit(-1);
00712                   }
00713                 if(lit != 0)
00714                   {
00715                       *(storeptr++) = lit; /* clause[i][size[i]] = j; */
00716                       freestore--;
00717                       numliterals++;
00718                       numoccurence[lit+MAXATOM]++;
00719                   }
00720             }
00721           while(lit != 0);
00722       }
00723     if(size[0] == 0)
00724       {
00725           fprintf(stderr,"ERROR - incorrect problem format or extraneous characters\n");
00726           exit(-1);
00727       }
00728 
00729     for(i = 0;i < 2*MAXATOM+1;i++)
00730       {
00731           if (freestore < numoccurence[i])
00732             {
00733                 storeptr = (int *) malloc( sizeof(int) * STOREBLOCK );
00734                 freestore = STOREBLOCK;
00735                 fprintf(stderr,"allocating memory...\n");
00736             }
00737           occurence[i] = storeptr;
00738           freestore -= numoccurence[i];
00739           storeptr += numoccurence[i];
00740           numoccurence[i] = 0;
00741       }
00742 
00743     for(i = 0;i < numclause;i++)
00744       {
00745           for(j = 0;j < size[i];j++)
00746             {
00747                 occurence[clause[i][j]+MAXATOM]
00748                   [numoccurence[clause[i][j]+MAXATOM]] = i;
00749                 numoccurence[clause[i][j]+MAXATOM]++;
00750             }
00751       }
00752 }
00753 
00754 
00755 void 
00756 fix(int tofix)
00757 {
00758     int numbreak[MAXLENGTH];    /* number of clauses changing */
00759     /* each atoms would make false */
00760     int i;                      /* loop counter */
00761     int j;                      /* another loop counter */
00762     int choice;
00763     static int (*pickcode[])(int *numbreak,int clausesize, int tofix) = 
00764       {pickrandom,pickproductsum,pickreciprocal,pickadditive,
00765          pickbest,pickexponential,picktabu};
00766 
00767     for(i = 0;i < size[tofix];i++)
00768       numbreak[i] = breakcost[abs(clause[tofix][i])];
00769 
00770     choice = (pickcode[heuristic])(numbreak,size[tofix],tofix);
00771     if (choice == NOVALUE)
00772       numnullflip++;
00773     else
00774       flipatom(abs(clause[tofix][choice]));
00775 }
00776 
00777 
00778 void flipatom(int toflip)
00779 {
00780     int i, j;                   /* loop counter */
00781     int toenforce;              /* literal to enforce */
00782     register int cli;
00783     register int lit;
00784     int numocc;
00785     register int sz;
00786     register int * litptr;
00787     int * occptr;
00788 
00789     changed[toflip] = numflip;
00790     if(atom[toflip] > 0)
00791       toenforce = -toflip;
00792     else
00793       toenforce = toflip;
00794     atom[toflip] = 1-atom[toflip];
00795     
00796     numocc = numoccurence[MAXATOM-toenforce];
00797     occptr = occurence[MAXATOM-toenforce];
00798     for(i = 0; i < numocc ;i++)
00799       {
00800           /* cli = occurence[MAXATOM-toenforce][i]; */
00801           cli = *(occptr++);
00802 
00803           if (--numtruelit[cli] == 0){
00804               false[numfalse] = cli;
00805               wherefalse[cli] = numfalse;
00806               numfalse++;
00807               costofnumfalse += cost[cli];
00808               /* Decrement toflip's breakcost */
00809               breakcost[toflip] -= cost[cli];
00810              if (cost[cli] == highestcost)
00811               { eqhighest = 1; numhighest++; }
00812           }
00813           else if (numtruelit[cli] == 1){
00814               /* Find the lit in this clause that makes it true, and inc its breakcount */
00815               sz = size[cli];
00816               litptr = clause[cli];
00817               for (j=0; j<sz; j++){
00818                   /* lit = clause[cli][j]; */
00819                   lit = *(litptr++);
00820                   if((lit > 0) == atom[abs(lit)]){
00821                       breakcost[abs(lit)] += cost[cli];
00822                       break;
00823                   }
00824               }
00825           }
00826       }
00827     
00828     numocc = numoccurence[MAXATOM+toenforce];
00829     occptr = occurence[MAXATOM+toenforce];
00830     for(i = 0; i < numocc; i++)
00831       {
00832           /* cli = occurence[MAXATOM+toenforce][i]; */
00833           cli = *(occptr++);
00834 
00835           if (++numtruelit[cli] == 1){
00836               numfalse--;
00837               costofnumfalse -= cost[cli];
00838                       false[wherefalse[cli]] =
00839                 false[numfalse];
00840               wherefalse[false[numfalse]] =
00841                 wherefalse[cli];
00842               /* Increment toflip's breakcount */
00843               breakcost[toflip] += cost[cli];
00844               if (cost[cli] == highestcost)
00845               { numhighest--; if (numhighest==0) eqhighest = 0; }
00846           }
00847           else if (numtruelit[cli] == 2){
00848               /* Find the lit in this clause other than toflip that makes it true,
00849                  and decrement its breakcount */
00850               sz = size[cli];
00851               litptr = clause[cli];
00852               for (j=0; j<sz; j++){
00853                   /* lit = clause[cli][j]; */
00854                   lit = *(litptr++);
00855                   if( ((lit > 0) == atom[abs(lit)]) &&
00856                      (toflip != abs(lit)) ){
00857                       breakcost[abs(lit)] -= cost[cli];
00858                       break;
00859                   }
00860               }
00861           }
00862       }
00863 }
00864 
00865 int pickrandom(int *numbreak,int clausesize, int tofix)
00866         /* returns a random number */
00867         {
00868         return(random()%clausesize);
00869         }
00870 
00871 int pickproductsum(int *numbreak,int clausesize, int tofix)
00872         /* weights each possibility by the */
00873         /* product of the product and sum of everything else */
00874         {
00875         int i;                             /* a loop counter */
00876         int weight[MAXLENGTH];             /* weights of each possibility */
00877         int tochange;                      /* value to return */
00878         int totalproduct = 1;              /* product of all numbreaks */
00879         int totalsum = 0;                  /* sum of all numbreaks */
00880 
00881         if(clausesize == 1)
00882                 return(0);
00883         if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
00884                 return(tochange);
00885         for(i = 0;i < clausesize;i++)
00886                 {
00887                 totalproduct *= numbreak[i];
00888                 totalsum += numbreak[i];
00889                 }
00890         for(i = 0;i < clausesize;i++)
00891                 {
00892                 weight[i] = (totalproduct/numbreak[i])*
00893                         (totalsum-numbreak[i]);
00894                 }
00895         return(pickweight(weight,clausesize));
00896         }
00897 
00898 int pickreciprocal(int *numbreak,int clausesize, int tofix)
00899         /* weights each possibility by its reciprocal*/
00900         {
00901         int i;                             /* a loop counter */
00902         int weight[MAXLENGTH];             /* weights of each possibility */
00903         int tochange;                      /* value to return */
00904         int totalproduct = 1;              /* product of all numbreaks */
00905 
00906         if(clausesize == 1)
00907                 return(0);
00908         if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
00909                 return(tochange);
00910         for(i = 0;i < clausesize;i++)
00911                 totalproduct *= numbreak[i];
00912         for(i = 0;i < clausesize;i++)
00913                 weight[i] = (totalproduct/numbreak[i]);
00914         return(pickweight(weight,clausesize));
00915         }
00916 
00917 int pickadditive(int *numbreak,int clausesize, int tofix)
00918         /* weights each possibility by the sum of the others */
00919         {
00920         int i;                             /* a loop counter */
00921         int weight[MAXLENGTH];             /* weights of each possibility */
00922         int tochange;                      /* value to return */
00923         int totalsum = 0;                  /* sum of all numbreaks */
00924 
00925         if(clausesize == 1)
00926                 return(0);
00927         if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
00928                 return(tochange);
00929         for(i = 0;i < clausesize;i++)
00930                 totalsum += numbreak[i];
00931         for(i = 0;i < clausesize;i++)
00932                 weight[i] = (totalsum-numbreak[i]);
00933         return(pickweight(weight,clausesize));
00934         }
00935 
00936 int pickbest(int *numbreak,int clausesize, int tofix)
00937 {
00938     int i;                      /* a loop counter */
00939     int best[MAXLENGTH];        /* best possibility so far */
00940     int numbest;                /* how many are tied for best */
00941     int bestvalue;              /* best value so far */
00942 
00943     numbest = 0;
00944     bestvalue = BIG;
00945 
00946     for (i=0; i< clausesize; i++){
00947         if (numbreak[i]<=bestvalue){
00948             if (numbreak[i]<bestvalue) numbest=0;
00949             bestvalue = numbreak[i];
00950             best[numbest++] = i;
00951         }
00952     }
00953 
00954     if (bestvalue>0 && (random()%denominator < numerator)){
00955 
00956         if (!hard || cost[tofix]>=highestcost) return(random()%clausesize); /* allow random breaks of hard clauses */
00957 
00958         /* only do a random walk breaking non-hard clauses */
00959 
00960         numbest = 0;
00961         for (i=0; i< clausesize; i++){
00962             if (numbreak[i]<highestcost){
00963                 best[numbest++] = i;
00964             }
00965         }
00966         /* if (numbest==0) { fprintf(stderr, "Wff is not feasible!\n"); exit(1); } */
00967         if (numbest==0) { return(random()%clausesize); }
00968     }
00969     if (numbest == 1) return best[0];
00970 
00971      //NOTE: Added this to avoid a crash when numbest is 0 in (random()%numbest)
00972     if (numbest==0) { return(random()%clausesize); }
00973 
00974     return(best[random()%numbest]); 
00975 
00976 
00977 
00978 }
00979 
00980 
00981 int 
00982 picktabu(int *numbreak,int clausesize, int tofix)
00983 {
00984     int i;                      /* a loop counter */
00985     int best[MAXLENGTH];        /* best possibility so far */
00986     int numbest;                /* how many are tied for best */
00987     int bestvalue;              /* best value so far */
00988     int tabu_level;
00989     int val;
00990 
00991     numbest = 0;
00992     bestvalue = BIG;
00993 
00994     if (numerator>0 && (random()%denominator < numerator)){
00995         for (i=0; i< clausesize; i++){
00996             if ((tabu_length < numflip - changed[abs(clause[tofix][i])]) ||
00997                 numbreak[i]==0){
00998                 if (numbreak[i]==0) numbest=0;
00999                 best[numbest++] = i;
01000             }
01001         }
01002     }
01003     else {
01004         for (i=0; i< clausesize; i++){
01005             if (numbreak[i]<=bestvalue && 
01006                 ((tabu_length < numflip - changed[abs(clause[tofix][i])]) ||
01007                  numbreak[i]==0)){
01008                 if (numbreak[i]<bestvalue) numbest=0;
01009                 bestvalue = numbreak[i];
01010                 best[numbest++] = i;
01011             }
01012         }
01013     }
01014     
01015     if (numbest == 0) return NOVALUE;
01016     if (numbest == 1) return best[0];
01017     return (best[random()%numbest]);
01018 }
01019 
01020 int pickexponential(int *numbreak,int clausesize, int tofix)
01021         {
01022         int i;                             /* a loop counter */
01023         int best[MAXLENGTH];               /* best possibility so far */
01024         int numbest;                       /* how many are tied for best */
01025         int bestvalue;                     /* best value so far */
01026         int weight[MAXLENGTH];             /* weights of each possibility */
01027         int tochange;                      /* value to return */
01028         int totalproduct = 1;              /* product of all numbreaks */
01029         int totalsum = 0;                  /* sum of all numbreaks */
01030 
01031         if(clausesize == 1)
01032                 return(0);
01033         if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
01034                 return(tochange);
01035         for(i = 0;i < clausesize;i++)
01036                 weight[i] = 2*2*2*2*2*2*2*2*2*2*2*2*2*2;
01037         for(i = 0;i < clausesize;i++)
01038                 {
01039                 weight[i] >>= numbreak[i]; /* weight[i] = weight[i]/(2^numbreak[i]) */
01040                 }
01041 
01042         return(pickweight(weight,clausesize));
01043         }
01044 
01045 int pickzero(int *numbreak,int clausesize)
01046         {
01047         int i;                /* loop counter */
01048         int numzero = 0;      /* number of zeros so far */
01049         int select;           /* random number */
01050 
01051         for(i = 0;i < clausesize;i++)
01052                 {
01053                 if(numbreak[i] == 0)
01054                         numzero++;
01055                 }
01056         if(numzero == 0)
01057                 return(NOVALUE);
01058         select = random()%numzero;
01059         for(i = 0;select >= 0;i++)
01060                 {
01061                 if(numbreak[i] == 0)
01062                         select--;
01063                 }
01064 
01065         return(i-1);
01066         }
01067 
01068 int pickweight(int *weight,int clausesize)
01069         {
01070         int i;                /* loop counter */
01071         int total = 0;        /* sum of weights */
01072         int select;           /* random number less than total */
01073         int subtotal = 0;
01074 
01075         for(i = 0;i < clausesize;i++)
01076                 total += weight[i];
01077         if(total == 0)
01078                 return(random()%clausesize);
01079         select = random()%total;
01080         for(i = 0;subtotal <= select;i++)
01081                 subtotal += weight[i];
01082         return(i-1);
01083         }
01084 
01085 int countunsat(void)
01086         {
01087         int i, j, unsat, bad, lit, sign;
01088 
01089         unsat = 0;
01090         for (i=0;i < numclause;i++)
01091                 {
01092                 bad = TRUE;
01093                 for (j=0; j < size[i]; j++)
01094                         {
01095                         lit = clause[i][j];
01096                         sign = lit > 0 ? 1 : 0;
01097                         if ( atom[abs(lit)] == sign )
01098                                 {
01099                                 bad = FALSE;
01100                                 break;
01101                                 }
01102                         }
01103                 if (bad)
01104                         unsat++;
01105                 }
01106         return unsat;
01107         }
01108 
01109 void countlowunsatcost(int * unsatcostptr, int * worstcostptr)
01110         {
01111         int i, j, bad, lit, sign, unsatcost, worstcost;
01112 
01113         unsatcost = 0;
01114         worstcost = 0;
01115         for (i=0;i < numclause;i++)
01116                 {
01117                 bad = TRUE;
01118                 for (j=0; j < size[i]; j++)
01119                         {
01120                         lit = clause[i][j];
01121                         sign = lit > 0 ? 1 : 0;
01122                         if ( lowatom[abs(lit)] == sign )
01123                                 {
01124                                 bad = FALSE;
01125                                 break;
01126                                 }
01127                         }
01128                 if (bad){
01129                         unsatcost += cost[i] ;
01130                         if (cost[i] > worstcost) worstcost = cost[i];
01131                     }
01132                 }
01133         * unsatcostptr = unsatcost;
01134         * worstcostptr = worstcost;
01135         return;
01136         }
01137 
01138 
01139 double 
01140 elapsed_seconds(void)
01141         {
01142         double answer;
01143 
01144         static struct rusage prog_rusage;
01145         static long prev_rusage_seconds = 0;
01146         static long prev_rusage_micro_seconds = 0;
01147 
01148         getrusage(0, &prog_rusage);
01149         answer = (double)(prog_rusage.ru_utime.tv_sec - prev_rusage_seconds)
01150                 + ((double)(prog_rusage.ru_utime.tv_usec - prev_rusage_micro_seconds)) / 
01151                 1000000.0 ;
01152         prev_rusage_seconds = prog_rusage.ru_utime.tv_sec ;
01153         prev_rusage_micro_seconds = prog_rusage.ru_utime.tv_usec ;
01154         return answer;
01155         }
01156 
01157 
01158 void
01159 print_low_assign(long int lowbad)
01160 {
01161     int i, j;
01162 
01163     printf("Begin assign with lowest # bad = %d (atoms assigned true)\n", lowbad);
01164     j=1;
01165     for (i=1; i<=numatom; i++){
01166         if (lowatom[i]>0){
01167             printf(" %d", i);
01168             if (j++ % 10 == 0) printf("\n");
01169         }
01170     }
01171     if ((j-1) % 10 != 0) printf("\n");
01172     printf("End assign\n");
01173 }
01174 
01175 void
01176 save_low_assign(void)
01177 {
01178     int i;
01179 
01180     for (i=1; i<=numatom; i++)
01181       lowatom[i] = atom[i];
01182 }
01183 
01184 int selecthigh(int high)
01185 {
01186   int counter=0;
01187   int i=0;
01188   while ((i<numfalse) && (counter<high))
01189   {
01190     if (cost[false[i]] == highestcost)
01191        counter++;
01192     i++;
01193   }
01194  /* fprintf(stderr, "The cost of the selected clause %i\n", cost[false[i-1]]);*/
01195   return(false[i-1]);
01196 }
01197    
01198 

Generated on Tue Jan 16 05:30:03 2007 for Alchemy by  doxygen 1.5.1