samplesat.h

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner and Hoifung Poon.
00006  * 
00007  * Copyright [2004-07] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00009  * Poon. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00032  * Poon in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #ifndef SAMPLESAT_H_OCT_23_2005
00067 #define SAMPLESAT_H_OCT_23_2005
00068 
00069 /************************************
00070  * Near-Uniform Sampler
00071  * Adapted for MC-SAT
00072  * Original:
00073     WalkSAT v45 by Kautz
00074     SampleSat by Wei et.al.
00075  ************************************/
00076 #define VERSION "samplesat-WSv45"
00077 #define UNIX 1
00078 
00079 // ---------------------------------- //
00080 // - Includes
00081 // ---------------------------------- //
00082 #include "samplesatparams.h"
00083 #include "array.h"
00084 #include "hashint.h"
00085 #include <assert.h>
00086 #include <iostream>
00087 using namespace std;
00088 
00089 #include <stdio.h>
00090 #include <string.h>
00091 #include <stdlib.h>
00092 #include <math.h>
00093 #include <sys/types.h>
00094 #include <limits.h>
00095 #include <signal.h>
00096 
00097 // -- UNIX
00098 #include <sys/times.h>
00099 #include <sys/time.h>
00100 
00101 // ---------------------------------- //
00102 // - Constants
00103 // ---------------------------------- //
00104 #ifdef DYNAMIC
00105   #define STOREBLOCK 2000000    /* size of block to malloc each time */
00106 #else
00107   #define STOREBLOCK 2000000    /* size of block to malloc each time */
00108 #endif
00109  
00110 #define BIGINT long int
00111 #ifndef CLK_TCK
00112   #define CLK_TCK 60
00113 #endif
00114 #define NOVALUE -1
00115 #define INIT_PARTIAL 1
00116 //#define HISTMAX 101           /* length of histogram of tail */
00117 #define HISTMAX 1               /* length of histogram of tail */
00118 #define BIG 100000000
00119 
00120 enum heuristics {RANDOM, BEST, TABU, SA};
00121 
00122 // ---------------------------------- //
00123 // - Class
00124 // ---------------------------------- //
00125 class SampleSat
00126 {
00127 public:
00128   SampleSat(const SampleSatParams & params, int numGndPreds, int maxClause,
00129             int maxLen, int maxLitOccurence, int* fixedAtoms, int** clauses,
00130             const Array<Array<int> >* const & blocks,
00131             const Array<bool>* const & blockEvidence);
00132   ~SampleSat();
00133   bool sample(bool*& assignments, int numClauses,
00134               const Array<Array<int> >* const & blocks,
00135               const Array<bool>* const & blockEvidence);
00136 
00137 private:
00138         // ---------------------------------- //
00139         // - variables
00140         // ---------------------------------- //
00141   int saRatio;       // saRatio/100: percentage of SA steps
00142   int temperature;   // temperature/100: fixed temperature for SA step
00143   bool latesa;
00144 
00145         // - WS data
00146         // = {pickrandom, pickbest, picktabu, picknovelty, pickrnovelty, 
00147         //    picknoveltyplus, pickrnoveltyplus, picksa};
00148   int (SampleSat::*pickcode[15])(void); 
00149 
00150   int numatom, MAXATOM;
00151   int numclause, MAXCLAUSE;
00152   int numliterals;
00153   int MAXLENGTH;                /* maximum number of literals which can be in any clause */
00154 
00155   int ** clause;                /* clauses to be satisfied */
00156                                         /* indexed as clause[clause_num][literal_num] */
00157   int * size;                   /* length of each clause */
00158   int * wfalse;         /* clauses which are false */
00159   int * lowfalse;
00160   int * wherefalse;     /* where each clause is listed in false */
00161   int * numtruelit;     /* number of true literals in each clause */
00162 
00163   int** occurence;
00164   int* numoccurence;
00165   int* atom;    
00166   int* lowatom;
00167   int* solution;
00168   int* changed;
00169   int* breakcount;
00170   int* makecount;
00171   int numfalse;
00172 
00173         // For unit propagation
00174   int* fixedatom;
00175   bool* isSat;
00176 
00177     // For block inference
00178   Array<Array<int> >* blocks_;
00179   Array<bool >* blockEvidence_;
00180     
00181     // Which other atom to flip in block
00182   bool inBlock;
00183   int flipInBlock;
00184     
00185     // Keeps track of old indices after unit prop.
00186   Array<int> newToOldMapping_;
00187     
00188   int* watch1;
00189   int* watch2;  
00190 
00191         // params
00192   int status_flag;   /* value returned from main procedure */
00193   int abort_flag;
00194 
00195   int heuristic;     /* heuristic to be used */
00196   int numerator;     /* make random flip with numerator/denominator frequency */
00197   int denominator;              
00198   int tabu_length;   /* length of tabu list */
00199 
00200   int wp_numerator;  /* walk probability numerator/denominator */
00201   int wp_denominator;           
00202 
00203   BIGINT numflip;    /* number of changes so far */
00204   BIGINT numnullflip;/*  number of times a clause was picked, but no  */
00205                                            /*  variable from it was flipped  */
00206   BIGINT cutoff;
00207   BIGINT base_cutoff;
00208   int target;
00209   int numtry;        /* total attempts at solutions */
00210 
00211   int numrun;
00212   int numsol;
00213 
00214   bool superlinear;
00215 
00216     // set to true by heuristics that require the make values to be calculated
00217   bool makeflag;
00218         
00219     /* Histogram of tail */
00220   long int tailhist[HISTMAX];   /* histogram of num unsat in tail of run */
00221   long histtotal;
00222   int tail;
00223   int tail_start_flip;
00224 
00225         /* Printing options */
00226   bool printonlysol;
00227   bool printsolcnf;
00228   bool printfalse;
00229   bool printlow;
00230   bool printhist;
00231   int printtrace;
00232   bool trace_assign;
00233 
00234   char outfile[1024];
00235 
00236         /* Initialization options */
00237   char initfile[100];
00238   int initoptions;
00239 
00240         /* Randomization */
00241   int seed;
00242 
00243  #ifdef UNIX
00244   struct timeval tv;
00245   struct timezone tzp;
00246  #endif
00247  #ifdef NT
00248   DWORD win_time;     // elapsed time in ms, since windows boot up
00249  #endif
00250 
00251         /* Statistics */
00252         double expertime;
00253         BIGINT flips_this_solution;
00254         long int lowbad;           /* lowest number of bad clauses during try */
00255         BIGINT totalflip;          /* total number of flips in all tries so far */
00256         BIGINT totalsuccessflip;   /* total number of flips in all tries which succeeded so far */
00257         int numsuccesstry;         /* total found solutions */
00258 
00259         BIGINT x;
00260         BIGINT integer_sum_x;
00261         double sum_x;
00262         double sum_x_squared;
00263         double mean_x;
00264         double second_moment_x;
00265         double variance_x;
00266         double std_dev_x;
00267         double std_error_mean_x;
00268         double seconds_per_flip;
00269         int r;
00270         int sum_r;
00271         double sum_r_squared;
00272         double mean_r;
00273         double variance_r;
00274         double std_dev_r;
00275         double std_error_mean_r;
00276 
00277         double avgfalse;
00278         double sumfalse;
00279         double sumfalse_squared;
00280         double second_moment_avgfalse, variance_avgfalse, std_dev_avgfalse, ratio_avgfalse;
00281         //double std_dev_avgfalse;
00282         double f;
00283         double sample_size;
00284 
00285         double sum_avgfalse;
00286         double sum_std_dev_avgfalse;
00287         double mean_avgfalse;
00288         double mean_std_dev_avgfalse;
00289         int number_sampled_runs;
00290         double ratio_mean_avgfalse;
00291 
00292         double suc_sum_avgfalse;
00293         double suc_sum_std_dev_avgfalse;
00294         double suc_mean_avgfalse;
00295         double suc_mean_std_dev_avgfalse;
00296         int suc_number_sampled_runs;
00297         double suc_ratio_mean_avgfalse;
00298 
00299         double nonsuc_sum_avgfalse;
00300         double nonsuc_sum_std_dev_avgfalse;
00301         double nonsuc_mean_avgfalse;
00302         double nonsuc_mean_std_dev_avgfalse;
00303         int nonsuc_number_sampled_runs;
00304         double nonsuc_ratio_mean_avgfalse;
00305 
00306         /* Hamming calcualations */
00307         char hamming_target_file[512];
00308         char hamming_data_file[512];
00309         int hamming_sample_freq;
00310         int hamming_flag;
00311         int hamming_distance;
00312         int* hamming_target;
00313         FILE * hamming_fp;
00314 
00315         /* Noise level */
00316         int samplefreq;
00317 
00318         // ---------------------------------- //
00319         // - utility
00320         // ---------------------------------- //
00321         void initRandom();
00322         void initVars();
00323         void print_parameters(int argc, char * argv[]);
00324 
00325         int Var(int c, int p) {return abs(clause[c][p]);}
00326         
00327         void parse_parameters(int argc,char *argv[])
00328         {
00329                 int i;
00330                 int temp;
00331 
00332                 // -- set SA param
00333                 heuristic = SA;
00334 
00335                 // -- parse params
00336                 for (i=1;i < argc;i++)
00337                 {
00338                 if (strcmp(argv[i],"-seed") == 0)
00339                         scanone(argc,argv,++i,&seed);
00340                 else if (strcmp(argv[i],"-out") == 0 && i<argc-1)
00341                         strcpy(outfile, argv[++i]);
00342                 else if (strcmp(argv[i],"-hist") == 0)
00343                         printhist = true;
00344                 else if (strcmp(argv[i],"-status") == 0)
00345                         status_flag = 1;
00346                 else if (strcmp(argv[i],"-cutoff") == 0)
00347                         scanonell(argc,argv,++i,&cutoff);
00348                 else if (strcmp(argv[i],"-late_sa")==0)
00349                         latesa = true;
00350                 else if (strcmp(argv[i],"-random") == 0)
00351                         heuristic = RANDOM;
00352                 else if (strcmp(argv[i],"-best") == 0)
00353                         heuristic = BEST;
00354                 else if (strcmp(argv[i],"-sa") == 0){
00355                         heuristic = SA;
00356                         makeflag = true;
00357                         scanone(argc, argv, ++i, &saRatio);
00358                         scanone(argc, argv, ++i, &temperature);
00359                 }
00360                 else if (strcmp(argv[i],"-noise") == 0){
00361                         scanone(argc,argv,++i,&numerator);
00362                         if (i < argc-1 && sscanf(argv[i+1],"%i",&temp)==1){
00363                         denominator = temp;
00364                         i++;
00365                         }
00366                 }
00367                         else if (strcmp(argv[i],"-wp") == 0){
00368                                 scanone(argc,argv,++i,&wp_numerator);
00369                                 if (i < argc-1 && sscanf(argv[i+1],"%i",&temp)==1){
00370                                         wp_denominator = temp;
00371                                         i++;
00372                                 }
00373                         }
00374                 else if (strcmp(argv[i],"-init") == 0  && i < argc-1)
00375                         sscanf(argv[++i], " %s", initfile);
00376                 else if (strcmp(argv[i],"-hamming") == 0  && i < argc-3){
00377                         sscanf(argv[++i], " %s", hamming_target_file);
00378                         sscanf(argv[++i], " %s", hamming_data_file);
00379                         sscanf(argv[++i], " %i", &hamming_sample_freq);
00380                         hamming_flag = true;
00381                         numrun = 1;
00382                 }
00383                 else if (strcmp(argv[i],"-partial") == 0)
00384                         initoptions = INIT_PARTIAL;
00385                 else if (strcmp(argv[i],"-super") == 0)
00386                         superlinear = true;
00387                 else if (strcmp(argv[i],"-tries") == 0 || strcmp(argv[i],"-restart") == 0)
00388                         scanone(argc,argv,++i,&numrun);
00389                 else if (strcmp(argv[i],"-target") == 0)
00390                         scanone(argc,argv,++i,&target);
00391                 else if (strcmp(argv[i],"-tail") == 0)
00392                         scanone(argc,argv,++i,&tail);
00393                 else if (strcmp(argv[i],"-sample") == 0)
00394                         scanone(argc,argv,++i,&samplefreq);
00395                 else if (strcmp(argv[i],"-tabu") == 0)
00396                 {
00397                         scanone(argc,argv,++i,&tabu_length);
00398                         heuristic = TABU;
00399                 }
00400                 else if (strcmp(argv[i],"-low") == 0)
00401                         printlow = true;
00402                 else if (strcmp(argv[i],"-sol") == 0)
00403                 {
00404                         printonlysol = true;
00405                         printlow = true;
00406                 }
00407                 else if (strcmp(argv[i],"-solcnf") == 0)
00408                 {
00409                         printsolcnf = true;
00410                         if (numsol == NOVALUE) numsol = 1;
00411                 }
00412                 else if (strcmp(argv[i],"-bad") == 0)
00413                         printfalse = true;
00414                 else if (strcmp(argv[i],"-numsol") == 0)
00415                         scanone(argc,argv,++i,&numsol);
00416                 else if (strcmp(argv[i],"-trace") == 0)
00417                         scanone(argc,argv,++i,&printtrace);
00418                 else if (strcmp(argv[i],"-assign") == 0){
00419                         scanone(argc,argv,++i,&printtrace);
00420                         trace_assign = true;
00421                 }
00422                 else 
00423                 {
00424                         fprintf(stderr, "General parameters:\n");
00425                         fprintf(stderr, "  -seed N -cutoff N -restart N\n");
00426                         fprintf(stderr, "  -numsol N = stop after finding N solutions\n");
00427                         fprintf(stderr, "  -super = use the Luby series for the cutoff values\n");
00428                         fprintf(stderr, "  -init FILE = set vars not included in FILE to false\n");
00429                         fprintf(stderr, "  -partial FILE = set vars not included in FILE randomly\n");
00430                         fprintf(stderr, "  -status = return fail status if solution not found\n");
00431                         fprintf(stderr, "  -target N = succeed if N or fewer clauses unsatisfied\n");
00432                         fprintf(stderr, "Heuristics:\n");
00433                         fprintf(stderr, "  -random -best -tabu N \n");
00434                         fprintf(stderr, "  -sa SA_RATIO TEMPERATURE walksat with SA_RATIO percent SA\n               moves added at temp TEMPERAURE/100. (default: -sa 50 10)\n");
00435                         fprintf(stderr, "  -late_sa  use mixed simulated annealing moves only at solution cluster\n");
00436                         fprintf(stderr, "  -noise N or -noise N M (default M = 100)\n");
00437                         fprintf(stderr, "Printing:\n");
00438                         fprintf(stderr, "  -out FILE = print solution as a list of literals to FILE\n");
00439                         fprintf(stderr, "  -trace N = print statistics every N flips\n");
00440                         fprintf(stderr, "  -assign N = print assignments at flip N, 2N, ...\n");
00441                         fprintf(stderr, "  -sol = print satisfying assignments to stdout\n");
00442                         fprintf(stderr, "  -solcnf = print sat assign to stdout in DIMACS format, and exit\n");
00443                         fprintf(stderr, "  -low = print lowest assignment each try\n");
00444                         fprintf(stderr, "  -bad = print unsat clauses each try\n");
00445                         fprintf(stderr, "  -hist = print histogram of tail\n");
00446                         fprintf(stderr, "  -tail N = assume tail begins at nvars*N\n");
00447                         fprintf(stderr, "  -sample N = sample noise level every N flips\n");
00448                         fprintf(stderr, "  -hamming TARGET_FILE DATA_FILE SAMPLE_FREQUENCY\n");
00449                         exit(-1);
00450                 }
00451                 }
00452                 base_cutoff = cutoff;
00453                 if (numsol==NOVALUE || numsol>numrun) numsol = numrun;
00454                 if (numerator==NOVALUE){
00455                 switch(heuristic) {
00456                 case BEST:
00457                 default:
00458                         numerator = 0;
00459                         break;
00460                 }
00461                 }
00462                 if (wp_numerator==NOVALUE){
00463                         switch(heuristic) {
00464                         default:
00465                         wp_numerator = 0;
00466                         break;
00467                         }
00468                 }
00469         }
00470 
00471 
00472 
00473         void print_statistics_header(void)
00474         {
00475                 /*
00476                 printf("numatom = %i, numclause = %i, numliterals = %i\n",numatom,numclause,numliterals);
00477                 printf("wff read in\n\n");
00478                 printf("    lowest     final       avg     noise     noise     total                 avg        mean        mean\n");
00479                 printf("    #unsat    #unsat     noise   std dev     ratio     flips              length       flips       flips\n");
00480                 printf("      this      this      this      this      this      this   success   success       until         std\n");
00481                 printf("       try       try       try       try       try       try      rate     tries      assign         dev\n\n");
00482 
00483                 fflush(stdout);
00484                 */
00485         }
00486 
00487         void initialize_statistics(void)
00488         {
00489                 x = 0; r = 0;
00490                 if (hamming_flag) {
00491                 read_hamming_file(hamming_target_file);
00492                 open_hamming_data(hamming_data_file);
00493                 }
00494                 tail_start_flip = tail * numatom;
00495                 //printf("tail starts after flip = %i\n", tail_start_flip);
00496                 numnullflip = 0;
00497         }
00498 
00499         void update_statistics_start_try(void)
00500         {
00501                 int i;
00502 
00503                 lowbad = numfalse;
00504 
00505                 sample_size = 0;
00506                 sumfalse = 0.0;
00507                 sumfalse_squared = 0.0;
00508 
00509                 for (i=0; i<HISTMAX; i++)
00510                 tailhist[i] = 0;
00511                 if (tail_start_flip == 0){
00512                 tailhist[numfalse < HISTMAX ? numfalse : HISTMAX - 1] ++;
00513                 }
00514                       
00515                 if (printfalse) save_false_clauses(lowbad);
00516                 if (printlow) save_low_assign();
00517         }
00518 
00519         void update_and_print_statistics_end_try(void);
00520 
00521         void print_statistics_start_flip(void) 
00522         {       
00523         if (printtrace && (numflip % printtrace == 0)){
00524                 printf(" %9li %9i                     %9li\n", lowbad,numfalse,numflip);
00525                 if (trace_assign)
00526                         print_current_assign();
00527                 fflush(stdout);
00528         }       
00529         }
00530 
00531         void update_statistics_end_flip(void)
00532         {
00533                 if (numfalse < lowbad){
00534                 lowbad = numfalse;      
00535                 if (printfalse) save_false_clauses(lowbad);
00536                 if (printlow) save_low_assign();
00537                 }
00538                 if (numflip >= tail_start_flip){
00539                 tailhist[(numfalse < HISTMAX) ? numfalse : (HISTMAX - 1)] ++;
00540                 if ((numflip % samplefreq) == 0){
00541                 sumfalse += numfalse;
00542                 sumfalse_squared += numfalse * numfalse;
00543                 sample_size ++;
00544                 }
00545                 }
00546         }
00547 
00548         void print_statistics_final(void)
00549         {
00550                 if (numsuccesstry > 0)
00551                 {
00552                   printf("ASSIGNMENT FOUND\n");
00553                   if (printsolcnf) print_sol_cnf();
00554                   if (outfile[0]) print_sol_file(outfile);
00555                 }
00556                 else
00557                   printf("ASSIGNMENT NOT FOUND\n");
00558         }
00559 
00560 
00561         static long super(int i)
00562         {
00563                 long power;
00564                 int k;
00565 
00566                 if (i<=0){
00567                 fprintf(stderr, "bad argument super(%d)\n", i);
00568                 exit(1);
00569                 }
00570                 /* let 2^k be the least power of 2 >= (i+1) */
00571                 k = 1;
00572                 power = 2;
00573                 while (power < (i+1)){
00574                 k += 1;
00575                 power *= 2;
00576                 }
00577                 if (power == (i+1)) return (power/2);
00578                 return (super(i - (power/2) + 1));
00579         }
00580 
00581         void handle_interrupt(int sig)
00582         {
00583                 if (abort_flag) exit(-1);
00584                 abort_flag = true;
00585         }
00586 
00587         void scanone(int argc, char *argv[], int i, int *varptr)
00588         {
00589                 if (i>=argc || sscanf(argv[i],"%i",varptr)!=1){
00590                 fprintf(stderr, "Bad argument %s\n", i<argc ? argv[i] : argv[argc-1]);
00591                 exit(-1);
00592                 }
00593         }
00594 
00595         void scanoneu(int argc, char *argv[], int i, unsigned int *varptr)
00596         {
00597                 if (i>=argc || sscanf(argv[i],"%u",varptr)!=1){
00598                 fprintf(stderr, "Bad argument %s\n", i<argc ? argv[i] : argv[argc-1]);
00599                 exit(-1);
00600                 }
00601         }
00602 
00603         void scanonell(int argc, char *argv[], int i, BIGINT *varptr)
00604         {
00605                 if (i>=argc || sscanf(argv[i],"%li",varptr)!=1){
00606                 fprintf(stderr, "Bad argument %s\n", i<argc ? argv[i] : argv[argc-1]);
00607                 exit(-1);
00608                 }
00609         }
00610 
00611 
00612         int calc_hamming_dist(int atom[], int hamming_target[], int numatom)
00613         {
00614                 int i;
00615                 int dist = 0;
00616             
00617                 for (i=1; i<=numatom; i++){
00618                 if (atom[i] != hamming_target[i]) dist++;
00619                 }
00620                 return dist;
00621         }
00622 
00623         void open_hamming_data(char initfile[])
00624         {
00625                 if ((hamming_fp = fopen(initfile, "w")) == NULL){
00626                 fprintf(stderr, "Cannot open %s for output\n", initfile);
00627                 exit(1);
00628                 }
00629         }
00630 
00631 
00632         void read_hamming_file(char initfile[])
00633         {
00634                 int i;                  /* loop counter */
00635                 FILE * infile;
00636                 int lit;    
00637 
00638                 printf("loading hamming target file %s ...", initfile);
00639 
00640                 if ((infile = fopen(initfile, "r")) == NULL){
00641                 fprintf(stderr, "Cannot open %s\n", initfile);
00642                 exit(1);
00643                 }
00644                 i=0;
00645                 for(i = 1;i < numatom+1;i++)
00646                 hamming_target[i] = 0;
00647 
00648                 while (fscanf(infile, " %d", &lit)==1){
00649                 if (abs(lit)>numatom){
00650                         fprintf(stderr, "Bad hamming file %s\n", initfile);
00651                         exit(1);
00652                 }
00653                 if (lit>0) hamming_target[lit]=1;
00654                 }
00655                 printf("done\n");
00656         }
00657 
00658 
00659         void
00660         print_false_clauses(long int lowbad)
00661         {
00662                 int i, j;
00663                 int cl;
00664 
00665                 printf("Unsatisfied clauses:\n");
00666                 for (i=0; i<lowbad; i++){
00667                 cl = lowfalse[i];
00668                 for (j=0; j<size[cl]; j++){
00669                         printf("%d ", clause[cl][j]);
00670                 }
00671                 printf("0\n");
00672                 }
00673                 printf("End unsatisfied clauses\n");
00674         }
00675 
00676         void
00677         save_false_clauses(long int lowbad)
00678         {
00679                 int i;
00680 
00681                 for (i=0; i<lowbad; i++)
00682                 lowfalse[i] = wfalse[i];
00683         }
00684         
00685         //void initprob(int numvararg, int numclausearg, int* wff)
00686         bool initprob();
00687 
00688     /* new flipping function based on SAT2004 submission work */
00689   void flipatom(int toflip)
00690   {
00691     int i, j;                   
00692     int toenforce;              
00693     register int cli;
00694     register int lit;
00695     int numocc;
00696     register int sz;
00697     register int * litptr;
00698     int * occptr;
00699     register int v;
00700                 /* printf("flipping %i\n", toflip); */
00701 
00702     if (toflip == NOVALUE)
00703     {
00704       numnullflip++;
00705       return;
00706     }
00707 
00708     changed[toflip] = numflip;
00709     if(atom[toflip] > 0)
00710     {
00711       toenforce = -toflip;
00712     }
00713     else
00714     {
00715       toenforce = toflip;
00716     }
00717     atom[toflip] = 1 - atom[toflip];
00718 
00719     if (hamming_flag)
00720     {
00721       if (atom[toflip] == hamming_target[toflip])
00722         hamming_distance--;
00723       else
00724         hamming_distance++;
00725       
00726       if ((numflip % hamming_sample_freq) == 0)
00727         fprintf(hamming_fp, "%li %i\n", numflip, hamming_distance);
00728     }
00729             
00730     numocc = numoccurence[MAXATOM - toenforce];
00731     occptr = occurence[MAXATOM - toenforce];
00732     for(i = 0; i < numocc ; i++)
00733     {
00734         /* cli = occurence[MAXATOM-toenforce][i]; */
00735       cli = *(occptr++);
00736 
00737       if (--numtruelit[cli] == 0)
00738       {
00739         wfalse[numfalse] = cli;
00740         wherefalse[cli] = numfalse;
00741         numfalse++;
00742           // Decrement toflip's breakcount
00743         breakcount[toflip]--;
00744 
00745         if (makeflag)
00746         {
00747                         // Increment the makecount of all vars in the clause
00748           sz = size[cli];
00749           litptr = clause[cli];
00750           for (j = 0; j < sz; j++)
00751           {
00752             /* lit = clause[cli][j]; */
00753             lit = *(litptr++);
00754             makecount[abs(lit)]++;
00755           }
00756         }
00757       }
00758       else if (numtruelit[cli] == 1)
00759       {
00760         if (watch1[cli] == toflip)
00761         {
00762           assert(watch1[cli] != watch2[cli]);
00763           watch1[cli] = watch2[cli];
00764         }
00765                 breakcount[watch1[cli]]++;
00766       }
00767       else 
00768       { /* numtruelit[cli] >= 2 */
00769         if (watch1[cli] == toflip)
00770         {
00771             /* find a true literal other than watch1[cli] and watch2[cli] */
00772           sz = size[cli];
00773           litptr = clause[cli];
00774           for (j = 0; j < sz; j++)
00775           {
00776             lit = *(litptr++);
00777             v = abs(lit);
00778             if ((lit>0) == atom[v] && v != watch1[cli] && v != watch2[cli])
00779             {
00780               watch1[cli] = v;
00781               break;
00782             }
00783           }
00784         }
00785         else
00786         if (watch2[cli] == toflip)
00787         {
00788             /* find a true literal other than watch1[cli] and watch2[cli] */
00789           sz = size[cli];
00790           litptr = clause[cli];
00791           for (j = 0; j < sz; j++)
00792           {
00793             lit = *(litptr++);
00794             v =abs(lit);
00795             if ((lit>0) == atom[v] && v != watch1[cli] && v != watch2[cli])
00796             {
00797               watch2[cli] = v;
00798               break;
00799             }
00800           }
00801         }
00802       }
00803     }
00804             
00805     numocc = numoccurence[MAXATOM+toenforce];
00806     occptr = occurence[MAXATOM+toenforce];
00807     for(i = 0; i < numocc; i++)
00808     {
00809         /* cli = occurence[MAXATOM+toenforce][i]; */
00810       cli = *(occptr++);
00811 
00812       if (++numtruelit[cli] == 1)
00813       {
00814         numfalse--;
00815         wfalse[wherefalse[cli]] = wfalse[numfalse];
00816         wherefalse[wfalse[numfalse]] = wherefalse[cli];
00817           // Increment toflip's breakcount
00818         breakcount[toflip]++;
00819 
00820         if (makeflag)
00821         {
00822             // Decrement the makecount of all vars in the clause
00823           sz = size[cli];
00824           litptr = clause[cli];
00825           for (j = 0; j < sz; j++)
00826           {
00827               /* lit = clause[cli][j]; */
00828             lit = *(litptr++);
00829             makecount[abs(lit)]--;
00830           }
00831         }
00832         watch1[cli] = toflip;
00833       }
00834       else
00835       if (numtruelit[cli] == 2)
00836       {
00837         watch2[cli] = toflip;
00838         breakcount[watch1[cli]]--;
00839       }
00840     }
00841   }
00842 
00843   int pickrandom(void)
00844   {
00845     int tofix;
00846 
00847     tofix = wfalse[random()%numfalse];
00848     return Var(tofix, random()%size[tofix]);
00849   }
00850 
00851   int pickbest(void)
00852   {
00853     int numbreak;
00854         int tofix;
00855         int clausesize;
00856         int i;          
00857         int best[MAXLENGTH];
00858         register int numbest;
00859         register int bestvalue;
00860         register int var;
00861 
00862     Array<int> canNotFlip;
00863       // If var in candidateBlockedVars is chosen, then
00864       // corresponding var in othersToFlip is flipped as well
00865     Array<int> candidateBlockedVars;
00866     Array<int> othersToFlip;
00867     
00868         tofix = wfalse[random()%numfalse];
00869         clausesize = size[tofix];
00870         numbest = 0;
00871         bestvalue = BIG;
00872 
00873         for (i = 0; i < clausesize; i++)
00874     {
00875           var = abs(clause[tofix][i]);
00876       int otherToFlip = NOVALUE;
00877       int blockIdx = getBlock(var - 1);
00878       if (blockIdx == -1) // Atom not in a block
00879         numbreak = breakcount[var];
00880       else // Atom is in a block
00881       {
00882           // If evidence atom exists or in block of size 1, then can not flip
00883         if ((*blockEvidence_)[blockIdx] || (*blocks_)[blockIdx].size() == 1)
00884         {
00885           numbreak = INT_MAX;
00886           //canNotFlip.append(var);
00887           canNotFlip.append(i);
00888         }
00889         else
00890         {
00891           numbreak = calculateNumbreak(var, otherToFlip);
00892           candidateBlockedVars.append(var);
00893           othersToFlip.append(otherToFlip);
00894         }
00895       }
00896 
00897           if (numbreak <= bestvalue)
00898       { // Tied or better than previous best
00899                 if (numbreak < bestvalue) numbest = 0;
00900                 bestvalue = numbreak;
00901                 best[numbest++] = var;
00902           }
00903         }
00904 
00905       // Choose one of the best at random
00906       // (default if none of the following 2 cases occur
00907     int toflip = best[random()%numbest];
00908 
00909       // 1. If at least 1 clause is broken by best,
00910       // then with prob. choose a random atom
00911         if (bestvalue > 0 && (random()%denominator < numerator))
00912       toflip = abs(clause[tofix][random()%clausesize]);
00913       // 2. Exactly one best atom
00914         else if (numbest == 1)
00915       toflip = best[0];
00916 
00917       // If atom can not be flipped, then null flip
00918     if (canNotFlip.contains(toflip)) toflip = NOVALUE;
00919     else
00920     { // If toflip is in block, then set other to flip
00921       int idx = candidateBlockedVars.find(toflip);
00922       if (idx >= 0)
00923       {
00924         inBlock = true;
00925         flipInBlock = othersToFlip[idx];
00926       }
00927     }
00928         return toflip;
00929   }
00930 
00931   int picktabu(void)
00932   {
00933     int numbreak[MAXLENGTH];
00934     int tofix;
00935     int clausesize;
00936     int i;                      /* a loop counter */
00937     int best[MAXLENGTH];        /* best possibility so far */
00938     int numbest;                /* how many are tied for best */
00939     int bestvalue;              /* best value so far */
00940     int noisypick;
00941 
00942     tofix = wfalse[random()%numfalse];
00943     clausesize = size[tofix];
00944     for(i = 0; i < clausesize; i++)
00945       numbreak[i] = breakcount[abs(clause[tofix][i])];
00946 
00947     numbest = 0;
00948         bestvalue = BIG;
00949 
00950         noisypick = (numerator > 0 && random()%denominator < numerator); 
00951         for (i = 0; i < clausesize; i++)
00952     {
00953       if (numbreak[i] == 0)
00954       {
00955                 if (bestvalue > 0)
00956         {
00957                   bestvalue = 0;
00958                   numbest = 0;
00959                 }
00960                 best[numbest++] = i;
00961           }
00962           else if (tabu_length < numflip - changed[abs(clause[tofix][i])])
00963       {
00964         if (noisypick && bestvalue > 0)
00965         { 
00966                   best[numbest++] = i; 
00967         }
00968         else
00969         {
00970           if (numbreak[i] < bestvalue)
00971           {
00972                         bestvalue = numbreak[i];
00973                         numbest = 0;
00974                   }
00975                   if (numbreak[i] == bestvalue)
00976           {
00977                         best[numbest++] = i; 
00978                   }
00979         }
00980       }
00981     }
00982         if (numbest == 0) return NOVALUE;
00983         if (numbest == 1) return Var(tofix, best[0]);
00984         return (Var(tofix, best[random()%numbest]));
00985   }
00986 
00987   int picksa(void);
00988 
00989   int countunsat(void)
00990   {
00991     int i, j, unsat, lit, sign;
00992     bool bad;
00993 
00994     unsat = 0;
00995     for (i = 0; i < numclause; i++)
00996     {
00997       bad = true;
00998       for (j = 0; j < size[i]; j++)
00999       {
01000         lit = clause[i][j];
01001         sign = lit > 0 ? 1 : 0;
01002         if ( atom[abs(lit)] == sign )
01003         {
01004           bad = false;
01005           break;
01006         }
01007       }
01008       
01009       if (bad) unsat++;
01010     }
01011     return unsat;
01012   }
01013 
01014 
01015         double elapsed_seconds(void) 
01016         { 
01017                 double answer;
01018 
01019         #ifdef ANSI
01020                 static long prev_time = 0;
01021                 time( &long_time );
01022                 /* Note:  time(&t) returns t in seconds, so do not need to /CLK_TCK */
01023                 answer = long_time - prev_time;
01024                 prev_time = long_time;
01025         #endif
01026         #ifdef NT
01027                 static DWORD prev_time = 0;
01028                 win_time = timeGetTime();
01029                 /* Note:  return value of timeGetTime() is ms, so divide by 1000*/
01030                 answer = (double)(win_time - prev_time) / (double)1000; 
01031                 prev_time = win_time;
01032         #endif
01033         #ifdef UNIX
01034                 static struct tms prog_tms;
01035                 static long prev_times = 0;
01036                 (void) times(&prog_tms);
01037                 answer = ((double)(((long)prog_tms.tms_utime)-prev_times))/((double) CLK_TCK);
01038                 prev_times = (long) prog_tms.tms_utime;
01039         #endif
01040                 return answer; 
01041         }
01042 
01043 
01044         void print_sol_cnf(void)
01045         {
01046                 int i;
01047                 for(i = 1;i < numatom+1;i++)
01048                 printf("v %i\n", solution[i] == 1 ? i : -i);
01049         }
01050 
01051 
01052         void print_sol_file(char * filename)
01053         {
01054                 FILE * fp;
01055                 int i;
01056 
01057                 if ((fp = fopen(filename, "w"))==NULL){
01058                 fprintf(stderr, "Cannot open output file\n");
01059                 exit(-1);
01060                 }
01061                 for(i = 1;i < numatom+1;i++){
01062                 fprintf(fp, " %i", solution[i] == 1 ? i : -i);
01063                 if (i % 10 == 0) fprintf(fp, "\n");
01064                 }
01065                 if ((i-1) % 10 != 0) fprintf(fp, "\n");
01066                 fclose(fp);
01067         }
01068 
01069 
01070   void print_low_assign(long int lowbad)
01071   {
01072     int i;
01073 
01074     printf("Begin assign with lowest # bad = %li\n", lowbad);
01075     for (i = 1; i <= numatom; i++)
01076     {
01077       printf(" %d", lowatom[i]==0 ? -i : i);
01078       if (i % 10 == 0) printf("\n");
01079     }
01080 
01081     if ((i-1) % 10 != 0) printf("\n");
01082     printf("End assign\n");
01083   }
01084 
01085   void print_current_assign(void)
01086   {
01087     int i;
01088 
01089     printf("Begin assign at flip = %li\n", numflip);
01090     for (i = 1; i <= numatom; i++)
01091     {
01092       printf(" %d", atom[i]==0 ? -i : i);
01093       if (i % 10 == 0) printf("\n");
01094     }
01095   
01096     if ((i-1) % 10 != 0) printf("\n");
01097     printf("End assign\n");
01098   }
01099 
01100   void save_low_assign(void)
01101   {
01102     int i;
01103 
01104     for (i = 1; i <= numatom; i++)
01105       lowatom[i] = atom[i];
01106   }
01107 
01108   void save_solution(void)
01109   {
01110     int i;
01111 
01112     for (i = 1; i <= numatom; i++)
01113       solution[i] = atom[i];
01114   }
01115 
01116     // Returns true if a fixed atom is in block, otherwise false    
01117   bool fixedAtomInBlock(const int blockIdx)
01118   {
01119     Array<int> block = (*blocks_)[blockIdx];
01120     for (int i = 0; i < block.size(); i++)
01121       if (fixedatom[block[i] + 1] > 0) return true;
01122     return false;
01123   }
01124 
01125     // Sets the truth values of all atoms in the
01126     // block blockIdx except for the one with index atomIdx
01127   void setOthersInBlockToFalse(bool*& assignments,
01128                                const int& atomIdx,
01129                                const int& blockIdx)
01130   {
01131     Array<int> block = (*blocks_)[blockIdx];
01132     for (int i = 0; i < block.size(); i++)
01133     {
01134       if (i != atomIdx)
01135         assignments[block[i]] = false;
01136     }
01137   }
01138 
01139     // Sets the truth values of all atoms in the
01140     // block blockIdx except for the one with index atomIdx
01141   void setOthersInBlockToFalse(const int& atomIdx,
01142                                const int& blockIdx)
01143   {
01144     Array<int> block = (*blocks_)[blockIdx];
01145     for (int i = 0; i < block.size(); i++)
01146     {
01147       if (i != atomIdx)
01148         atom[block[i] + 1] = 0;
01149     }
01150   }
01151 
01152     // returns the index of the block which the atom
01153     // with index atomIdx is in. If not in any, returns -1
01154   int getBlock(const int& atomIdx)
01155   {
01156     for (int i = 0; i < blocks_->size(); i++)
01157     {
01158       int blockIdx = (*blocks_)[i].find(atomIdx);
01159       if (blockIdx >= 0)
01160         return i;
01161     }
01162     return -1;
01163   }
01164     
01165     // Calculates the change in clauses satisfied by flipping atom
01166     // and stores idx of other atom to flip in block in flipInBlock
01167   int calculateChange(const int& atomIdx)
01168   {
01169     int blockIdx = getBlock(atomIdx - 1);
01170     assert(blockIdx >= 0);
01171       
01172       //Dealing with atom in a block
01173     Array<int> block = (*blocks_)[blockIdx];
01174     int chosen = -1;
01175     
01176       // 0->1: choose atom in block which is already 1
01177     if (atom[atomIdx] == 0)
01178     {
01179       for (int i = 0; i < block.size(); i++)
01180       {
01181         if (atom[block[i] + 1] == 1)
01182         {
01183           chosen = i;
01184           break;
01185         }
01186       }
01187     }
01188       // 1->0: choose to flip from others at random
01189     else
01190     {
01191       bool ok = false;
01192       while(!ok)
01193       {
01194         chosen = random() % block.size();
01195         if (block[chosen] + 1 != atomIdx)
01196           ok = true;
01197       }
01198     }
01199     
01200     assert(chosen >= 0);
01201     inBlock = true;
01202     flipInBlock = block[chosen] + 1;
01203     return makecount[atomIdx] + makecount[flipInBlock] -
01204            breakcount[atomIdx] - breakcount[flipInBlock];    
01205   }
01206   
01207     // Calculates the breakcost by flipping atom
01208     // and stores idx of other atom to flip in block in flipInBlock
01209   int calculateNumbreak(const int& atomIdx, int& otherToFlip)
01210   {
01211     int blockIdx = getBlock(atomIdx - 1);
01212     assert(blockIdx >= 0);
01213 
01214       //Dealing with atom in a block
01215     Array<int> block = (*blocks_)[blockIdx];
01216     int chosen = -1;
01217     
01218       // 0->1: choose atom in block which is already 1
01219     if (atom[atomIdx] == 0)
01220     {
01221       for (int i = 0; i < block.size(); i++)
01222       {
01223         if (atom[block[i] + 1] == 1)
01224         {
01225           chosen = i;
01226           break;
01227         }
01228       }
01229     }
01230       // 1->0: choose to flip the other randomly
01231       // TODO: choose to flip the other with best breakcost
01232     else
01233     {
01234       bool ok = false;
01235       while(!ok)
01236       {
01237         chosen = random() % block.size();
01238         if (block[chosen] + 1 != atomIdx)
01239           ok = true;
01240       }
01241     }
01242     
01243     assert(chosen >= 0);
01244     otherToFlip = block[chosen] + 1;
01245     return breakcount[atomIdx] + breakcount[otherToFlip];    
01246   }
01247 };
01248 
01249 #endif
01250 

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