lazywalksat.cpp

00001 /* This code is based on the MaxWalkSat package of Kautz et al. */
00002 #include "lazywalksat.h"
00003 #include "lwutil.h"
00004 #include "lwinfo.h"
00005 #include "timer.h"
00006 
00007 LazyWalksat::LazyWalksat(LWInfo *lwInfo, int memLimit)
00008 {
00009   clauseStorePtr = NULL;
00010   clauseFreeStore = 0;
00011    
00012   atomStorePtr = NULL;
00013   atomFreeStore = 0;
00014    
00015   atomFSMgr = new FreeStoreManager(BLOCKSIZE);
00016   clauseFSMgr = new FreeStoreManager(BLOCKSIZE);
00017    
00018   costexpected = true;   
00019   hard = 0;
00020   noApprox = false;
00021 
00022   this->lwInfo = lwInfo;
00023   this->memLimit = memLimit;
00024   clauseLimit = INT_MAX;
00025   haveDeactivated = false;
00026   
00027   numatom = 0;
00028   basenumatom = 0;
00029   numclause = 0;
00030   numliterals = 0;
00031    
00032   //currently allocated memory (in terms of number of items
00033   //that can be stored). This is a pointer and hence no memory has
00034   // been allocated yet
00035   clausemem = 0;
00036   atommem = 0;
00037 
00038   //fixedAtoms_.growToSize(lwInfo->getNumDBAtoms() + 1, false);
00039   maxFixedAtoms = lwInfo->getNumDBAtoms() + 1;
00040   fixedAtoms_ = new bool[maxFixedAtoms];
00041   for (int i = 0; i < maxFixedAtoms; i++)
00042     fixedAtoms_[i] = false;
00043   
00044 }
00045 
00046 LazyWalksat::~LazyWalksat()
00047 {
00048   clauseFSMgr->releaseAllStorePtr();
00049   atomFSMgr->releaseAllStorePtr();
00050  
00051   deleteClauseMemory();
00052   deleteAtomMemory();
00053                   
00054   delete clauseFSMgr;
00055   delete atomFSMgr;
00056   
00057   for(int i = 0; i < newClauses.size(); i++)
00058     delete newClauses[i];
00059   newClauses.clear();
00060   newClauseWeights.clear();
00061 
00062   for(int i = 0; i < allClauses.size(); i++)
00063     delete allClauses[i];
00064   allClauses.clear();
00065   allClauseWeights.clear();
00066   
00067   for(int i = 0; i < supersetClauses_.size(); i++)
00068   {
00069     supersetClauses_[i]->deleteIntPredicates();
00070     delete supersetClauses_[i];
00071   }
00072   supersetClauses_.clear();
00073 
00074   delete [] fixedAtoms_;
00075 }
00076 
00077 /* Retrieves initial active atoms and randomizes them*/
00078 void LazyWalksat::randomizeActiveAtoms()
00079 {
00080   lwInfo->getWalksatClauses(newClauses, newClauseWeights);
00081   for(int i = 0; i < newClauses.size(); i++)
00082     delete newClauses[i];
00083 
00084   newClauses.clear();
00085   newClauseWeights.clear();
00086 
00087   for(int i = 1; i < lwInfo->getVarCount() + 1; i++)
00088   {
00089     lwInfo->setVarVal(i, random()%2);
00090   }
00091 }
00092 
00093 /* Lazy version of SampleSat */
00094 bool LazyWalksat::sample(const MaxWalksatParams* const & mwsParams,
00095                                                  const SampleSatParams& sampleSatParams,
00096                          const bool& initial)
00097 {
00098         // -- samplesat params
00099   saRatio = sampleSatParams.saRatio;
00100   temperature = sampleSatParams.temperature;
00101   latesa = sampleSatParams.latesa;
00102   numerator = sampleSatParams.ws_noise;
00103   
00104   int numsol = sampleSatParams.numsol;
00105 
00106         //Run LazyWalkSAT
00107   bool includeUnsatSolutions = false;
00108   Array<Array<bool>*> solutions;
00109   Array<int> numBad;
00110   infer(mwsParams, numsol, includeUnsatSolutions,
00111                 solutions, numBad, initial);
00112 
00113   for(int i = 0; i < newClauses.size(); i++)
00114     delete newClauses[i];
00115   newClauses.clear();
00116   newClauseWeights.clear();
00117 
00118   for(int i = 0; i < allClauses.size(); i++)
00119     delete allClauses[i];
00120   allClauses.clear();
00121   allClauseWeights.clear();
00122 
00123   int solutionsSize = solutions.size();  
00124         // Delete solutions array
00125   for (int i = 0; i < solutions.size(); i++)  
00126     if (solutions[i]) delete solutions[i];
00127   solutions.clearAndCompress();
00128   
00129   if (solutionsSize >= 1)
00130         return true;
00131   else
00132         return false;
00133 }
00134 
00135 
00136 /* Lazy version of MaxWalkSat */
00137 void LazyWalksat::infer(const MaxWalksatParams* const & params,
00138                                                 const int& numSolutions, const bool&  includeUnsatSolutions,
00139                                 Array<Array<bool>*>& solutions, Array<int>& numBad,
00140                                 const bool& initial)
00141 {
00142 //cout << "Inside lazywalksat::infer" << endl;
00143   int base_cutoff = 100000;
00144   bool printonlysol = false;
00145   bool printfalse = false;
00146   bool printlow = true;
00147   int printtrace = 1000;
00148   //int printtrace = 0;
00149   long int totalflip = 0;       /* total number of flips in all tries so far */
00150   int numtry = 0;               /* total attempts at solutions */
00151   int numsuccesstry = 0;        /* total found solutions */
00152   int numsol = numSolutions;     /* stop after this many tries succeeds */
00153   int seed;                     /* seed for random */
00154   struct timeval tv;
00155   struct timezone tzp;
00156   double setuptime;
00157   double expertime;
00158   double totaltime;
00159     
00160   long int lowbad;              /* lowest number of bad clauses during try */
00161   long int lowcost;             /* lowest cost of bad clauses during try */
00162   double seconds_per_flip;
00163 
00164   int worst_cost, computed_cost;
00165 
00166   gettimeofday(&tv,&tzp);
00167   seed = (( tv.tv_sec & 0177 ) * 1000000) + tv.tv_usec;
00168   srandom(seed);
00169 
00170   heuristic = BEST;
00171   numerator = NOVALUE;
00172   denominator = 100;
00173 
00174   int targetcost = params->targetWt;    /* the cost at which the program terminates*/
00175   if (targetcost == INT_MAX) targetcost = 0;
00176   if (params->hard) hard = true;
00177 
00178   int cutoff = params->maxSteps;
00179   int numrun = params->tries;
00180 
00181     // No. of runs must be at least as big as no. of solutions
00182   if (numrun < numsol) numrun = numsol;
00183   if (params->lazyNoApprox) noApprox = true;
00184   
00185   base_cutoff = cutoff;
00186   if (numerator == NOVALUE)
00187   {
00188         if (heuristic == BEST)
00189           numerator = 50;
00190         else
00191           numerator = 0;
00192   }
00193 
00194         // Make an approximation of how many clauses memory can hold
00195   if (memLimit > 0)
00196   {
00197           // Size of a clause (1 2-dim array and 5 1-dim arrays of ints)
00198           // and average one atom appears in 5 clauses
00199           // Size of an atom (1 2-dim array and 8 1-dim arrays of ints)
00200         int atomSize = 2*sizeof(int)*sizeof(int) + 11*sizeof(int);
00201         int clauseSize = (2 * ((sizeof(int)*sizeof(int) + 5*sizeof(int))
00202                                           + atomSize / 5));
00203           // About 50% of the memory is available (other 50% needed for DB, etc.)
00204         clauseLimit = ((memLimit/2) / clauseSize) * 1024;
00205         //cout << "Max. no. of clauses memory can hold: " << clauseLimit << endl;
00206   }
00207 
00208   setuptime = 0;
00209   expertime = 0;
00210   elapsed_seconds();
00211   
00212   if (initial)
00213   {
00214     init();
00215   }
00216   else if (lwInfo->getSampleSat())
00217   {
00218     newClauses.clear();
00219     newClauseWeights.clear();
00220 /*
00221 for (int i = 0; i < supersetClauses_.size(); i++)
00222 {
00223   cout << "Superset " ;
00224   supersetClauses_[i]->print(cout);
00225   cout << endl;
00226 }
00227 */
00228       // Deactivate atoms activated in last MC-SAT step
00229     resetSampleSat();
00230       // Do MC-SAT clause selection
00231     lwInfo->selectClauses(supersetClauses_, newClauses,
00232                           newClauseWeights);
00233       // Unit propagation on active clauses
00234     initFixedAtoms(newClauses, newClauseWeights);
00235     lwInfo->propagateFixedAtoms(newClauses, newClauseWeights,
00236                                 fixedAtoms_, maxFixedAtoms);
00237     
00238     clauseFSMgr->releaseAllStorePtr();
00239     atomFSMgr->releaseAllStorePtr();
00240  
00241     deleteClauseMemory();
00242     deleteAtomMemory();
00243           
00244     delete clauseFSMgr;
00245     delete atomFSMgr;
00246 
00247     clauseStorePtr = NULL;
00248     clauseFreeStore = 0;
00249    
00250     atomStorePtr = NULL;
00251     atomFreeStore = 0;
00252    
00253     atomFSMgr = new FreeStoreManager(BLOCKSIZE);
00254     clauseFSMgr = new FreeStoreManager(BLOCKSIZE);
00255    
00256     numatom = 0;
00257     numclause = 0;
00258     numliterals = 0;
00259     numfalse = 0;
00260     costofnumfalse = 0;
00261   
00262       //adding the clauses
00263     bool initial = true;
00264     addNewClauses(initial);
00265   }
00266   
00267   setuptime =  elapsed_seconds();
00268         
00269   abort_flag = false;
00270   numnullflip = 0;
00271   lowcost = BIG;
00272 
00273   
00274   for (int k = 0; k < numrun; k++)
00275   {
00276         initrun();
00277         lowbad = numfalse; 
00278         lowcost = costofnumfalse;
00279         save_low_assign();
00280         numflip = 0;
00281         
00282     //if (superlinear) cutoff = base_cutoff * super(r+1);
00283 
00284     if (printtrace)
00285     {
00286       cout<<"in the beginning, costofnumfalse = "<<costofnumfalse<<endl; 
00287       cout<<"cutoff = "<<cutoff<<endl;
00288       cout<<"numflip = "<<numflip<<endl;
00289       cout<<"numfalse = "<<numfalse<<endl;
00290       cout<<"numclause = "<<numclause<<endl;
00291       cout<<"targetcost = "<<targetcost<<endl;
00292       cout<<"hard = "<<hard<<endl;
00293             
00294       cout<<"costofnumfalse \t  numfalse \t numflip \t numclause"<<endl;
00295     }
00296 
00297         while((numflip < cutoff) /* && (costofnumfalse > targetcost) */)
00298     {
00299       if (numclause == 0) break;
00300           if (printtrace && (numflip % printtrace == 0))
00301           {
00302                 printf("%10i \t %10i \t %10li \t %10i\n",
00303                            costofnumfalse, numfalse, numflip, numclause);
00304                 fflush(stdout);
00305           }
00306         
00307           numflip++;
00308 
00309                 //If memory is getting full, then deactivate some atoms
00310           if (numclause > clauseLimit)
00311           {
00312                 trimClauses();
00313                 initrun();
00314                 lowbad = numfalse; 
00315                 lowcost = costofnumfalse;
00316                 save_low_assign();
00317                 continue;
00318           }
00319 
00320         // If samplesat, then try sim. annealing first
00321       if (!lwInfo->getSampleSat() || !simAnnealing())
00322       {
00323         if (hard && eqhighest && costexpected)
00324         {
00325                   fix(selecthigh(1 + random()%numhighest));
00326         }
00327         else
00328         {
00329                   fix(falseclause[random()%numfalse]);
00330         }
00331       }
00332 
00333           if (costofnumfalse <= lowcost)
00334           {
00335                 lowcost = costofnumfalse;
00336                 lowbad = numfalse;
00337                 save_low_assign();
00338           }
00339       
00340       if (costofnumfalse <= targetcost)
00341         break;
00342         }
00343           
00344         numtry++;
00345         totalflip += numflip;
00346         if(costofnumfalse <= targetcost)
00347         {
00348           numsuccesstry++;
00349         }
00350 
00351         countlowunsatcost(&computed_cost, &worst_cost);
00352           
00353           // Fill the solutions array
00354         if (printlow && (!printonlysol || costofnumfalse <= targetcost))
00355         {
00356       if (includeUnsatSolutions || lowbad == 0) 
00357       {
00358         Array<bool>* solution = new Array<bool>(numatom);
00359         for (int i = 0; i < numatom; i++) solution->append(false);
00360 
00361                 for (int i = 1; i <= numatom; i++)
00362                 {
00363                   if (lowatom[i] == 1) (*solution)[i-1] = true;
00364                   else (*solution)[i-1] = false;
00365                 }          
00366         solutions.append(solution);
00367         numBad.append(lowbad);
00368       }
00369         }
00370         if (numfalse > 0 && printfalse)
00371           print_false_clauses_cost(lowbad);
00372     
00373         if (numsuccesstry >= numsol) break;
00374         if (abort_flag) break;
00375         fflush(stdout);
00376   }
00377 
00378     // Now, set the db values to the best values observed
00379   lwInfo->setVarVals(lowatom);
00380 
00381     // Set evidence from unit prop. back to non-evidence
00382   if (lwInfo->getSampleSat())
00383     undoFixedAtoms();
00384   
00385   expertime += elapsed_seconds();
00386   totaltime = setuptime + expertime;
00387   seconds_per_flip = expertime / totalflip;
00388   
00389   
00390   return;
00391 }
00392 
00393 int LazyWalksat::getNumInitClauses()
00394 {
00395   return initClauseCount;
00396 }
00397 
00398 int LazyWalksat::getNumInitAtoms()
00399 {
00400   return initAtomCount;
00401 }
00402 
00403 int LazyWalksat::getNumClauses()
00404 {
00405   return numclause;
00406 }
00407 
00413 void LazyWalksat::resetSampleSat()
00414 { 
00415     // Set all subsequently activated atoms to inactive and false
00416   for(int atom = basenumatom + 1; atom <= numatom; atom++)
00417   {
00418     lwInfo->setVarVal(atom, false);
00419     lwInfo->setInactive(atom);
00420   }
00421 
00422     // Remove all activated clauses
00423   for(int i = allClauses.size() - 1; i >= 0; i++)
00424   {
00425     delete allClauses[i];
00426     allClauses.removeLastItem();
00427     allClauseWeights.removeLastItem();
00428   }
00429   allClauses.shrinkToSize(initClauseCount);
00430   numclause = 0;
00431 }
00432 
00433 
00434 /*******************************************************************************/
00435 /****************************** PRIVATE FUNCTIONS ****************************/
00436 /*******************************************************************************/
00437 
00438 
00445 void LazyWalksat::init()
00446 {
00447   Timer timer;
00448   double begSec = timer.time(); 
00449     //should be input by user ideally
00450     //highestcost=1;
00451   highestcost = BIG;
00452   
00453   numclause = 0;
00454   numatom = 0;
00455   numliterals = 0;
00456   //cout<<"inside init (lazywalksat.cpp) "<<endl;
00457 
00458     // If SampleSat, we want to get the superset of initial clauses
00459   bool sample = lwInfo->getSampleSat();
00460   
00461   for(int i = 0; i < newClauses.size(); i++)
00462     delete newClauses[i];
00463   newClauses.clear();
00464   newClauseWeights.clear();
00465 
00466   int defaultCnt = 0;
00467   double defaultCost = 0;
00468     //getting the initial set of active atoms
00469   if (sample)
00470   {
00471     lwInfo->getSupersetClauses(supersetClauses_);
00472 
00473     defaultCnt = supersetClauses_.size();
00474     for(int i = 0; i < defaultCnt; i++)
00475       defaultCost += supersetClauses_[i]->getWt();
00476 
00477     for(int i = 0; i < supersetClauses_.size(); i++)
00478     {
00479       supersetClauses_[i]->deleteIntPredicates();
00480       delete supersetClauses_[i];
00481     }
00482 
00483     supersetClauses_.clear();
00484   }
00485   else
00486   {
00487     lwInfo->getWalksatClauses(newClauses, newClauseWeights);  
00488     for(int i = 0; i < newClauses.size(); i++)
00489       delete newClauses[i];
00490 
00491     defaultCnt = newClauses.size();
00492     for(int i = 0; i < defaultCnt; i++)
00493       defaultCost += newClauseWeights[i];
00494 
00495     newClauses.clear();
00496     newClauseWeights.clear();
00497   }
00498 
00499   cout<<endl;
00500   cout<<"Default => Cost\t"<<"******\t"<<" Clause Cnt\t"<<endl;
00501   cout<<"           "<<defaultCost<<"\t"<<"******\t"<<defaultCnt<<"\t"<<endl<<endl;
00502 
00503   basenumatom = lwInfo->getVarCount();
00504   cout << "Number of Baseatoms = " << basenumatom << endl;
00505 
00506   for(int i = 1; i < basenumatom + 1; i++) 
00507         lwInfo->setActive(i);
00508   
00509         //getting the initial set of active clauses
00510   if (sample)
00511   {
00512     lwInfo->getSupersetClauses(supersetClauses_);
00513       // Do clause selection on superset and convert weights
00514 
00515 cout << "Superset:" << endl;
00516 lwInfo->printIntClauses(supersetClauses_);
00517 
00518     lwInfo->selectClauses(supersetClauses_, newClauses,
00519                           newClauseWeights);
00520     initFixedAtoms(newClauses, newClauseWeights);
00521     lwInfo->propagateFixedAtoms(newClauses, newClauseWeights,
00522                                 fixedAtoms_, maxFixedAtoms);
00523     
00524   }
00525   else
00526     lwInfo->getWalksatClauses(newClauses, newClauseWeights);
00527         
00528         //adding the clauses
00529   bool initial = true;
00530   addNewClauses(initial);
00531 
00532   initAtomCount = lwInfo->getVarCount();
00533   initClauseCount = allClauses.size();
00534 
00535   cout << "Atoms in memory: " << initAtomCount << endl;
00536   cout << "Initial active clauses: " << initClauseCount << endl;
00537 
00538   cout << "time taken for init = "; Timer::printTime(cout, timer.time()-begSec);
00539   cout << endl;
00540 }
00541 
00542 
00543 /* initialize a particular run */
00544 void LazyWalksat::initrun()
00545 {
00546   //cout<<"****** inside initrun *****"<<endl;
00547   int newval; 
00548   numfalse = 0;
00549   costofnumfalse = 0;
00550   eqhighest = false;
00551   numhighest = 0;
00552 
00553     // Blocks have been initialized in LWInfo
00554     
00555   for(int i = 1; i < numatom + 1; i++)
00556   {
00557         changed[i] = -BIG;
00558         breakcost[i] = 0;
00559 
00560     if (fixedAtoms_[i])
00561     {
00562       newval = lwInfo->getVarVal(i);
00563     }
00564     else
00565     {
00566       if (i <= basenumatom && !lwInfo->inBlock(i))
00567         newval = random()%2;
00568       else
00569         newval = initatom[i];
00570     }
00571 
00572     if (atom[i] != newval)
00573     {
00574       lwInfo->flipVar(i);
00575       atom[i] = newval;
00576     }
00577   }
00578   initializeBreakCost(0);
00579   //cout<<"****** leaving initrun *****"<<endl;
00580   
00581 }
00582 
00583 /* Fixes false clause (index of clause is tofix) */
00584 void LazyWalksat::fix(int tofix)
00585 {
00586   Timer timer;
00587   //double begSec = timer.time();
00588   double interimSec;
00589   //cout << "Fixing clause ";
00590     // If neg. clause, then flip all true literals
00591   if (cost[tofix] < 0)
00592   {
00593     //cout << "(neg.)" << endl;
00594     if (numtruelit[tofix] > 0)
00595     {
00596       for (int i = 0; i < size[tofix]; i++)
00597       {
00598         int atm = abs(clause[tofix][i]);
00599           // true literal
00600         if((clause[tofix][i] > 0) == atom[atm])
00601         {
00602           //cout << "\tTrue lit. " << i << ": ";
00603             // If atm has been deactivated or in block with evidence
00604             // or fixed, then do not flip it
00605           if ((haveDeactivated && lwInfo->isDeactivated(atm)) ||
00606               (lwInfo->inBlockWithEvidence(atm)))
00607             continue;
00608         
00609           if(!lwInfo->isActive(atm))
00610           {
00611             interimSec = timer.time();
00612             
00613               // If atom is in a block, this is noted here in lwInfo
00614             lwInfo->getWalksatClausesWhenFlipped(atm, newClauses, newClauseWeights);
00615          
00616             bool initial = false;
00617             addNewClauses(initial);
00618             lwInfo->setActive(atm);
00619             
00620             //cout << "time taken for non-active = "; Timer::printTime(cout, timer.time()-interimSec);
00621           }
00622           else
00623           {
00624               // Have to check if in block and get other to flip
00625             if (lwInfo->inBlock(atm))
00626             {
00627               lwInfo->chooseOtherToFlip(atm, newClauses, newClauseWeights);
00628               bool initial = false;
00629               addNewClauses(initial);
00630             }
00631           }
00632 
00633           if (lwInfo->getInBlock())
00634             lwInfo->setActive(lwInfo->getOtherAtom());
00635 
00636           flipatom(atm);
00637           if (lwInfo->getInBlock())
00638           {
00639             flipatom(lwInfo->getOtherAtom());
00640           }          
00641 
00642           lwInfo->flipVar(atm);
00643           if (lwInfo->getInBlock())
00644             lwInfo->flipVar(lwInfo->getOtherAtom());
00645 
00646             // Set back inBlock and other atom
00647           lwInfo->setInBlock(false);
00648           lwInfo->setOtherAtom(-1);
00649 
00650           //cout << endl;
00651         }
00652       }
00653     }
00654       // No true lits
00655     else
00656     {
00657       numnullflip++;
00658     }
00659   }
00660     // Pos. clause: choose an atom to flip
00661   else
00662   {
00663     //cout << "(pos.)" << endl;
00664     int numbreak[MAXLENGTH];    /* number of clauses changing */
00665                                 /* each atoms would make false */
00666     int i;                      /* loop counter */
00667     int choice;
00668 
00669     for(i = 0; i < size[tofix]; i++)
00670     {
00671       //cout << "\tLit. " << i << ": ";
00672       int atm = abs(clause[tofix][i]);
00673         
00674         // If atm has been deactivated or in block with evidence or fixed,
00675         // then give it a very high weight (do not want to flip)
00676           if ((haveDeactivated && lwInfo->isDeactivated(atm)) ||
00677           (lwInfo->inBlockWithEvidence(atm))) 
00678           {
00679         numbreak[i] = INT_MAX;
00680         continue;
00681       }
00682         
00683           //interfacing with external world - if this atom is not active,
00684           //need to get the cost of clauses which would become unsatisfied
00685           //by flipping it. 
00686       if(!lwInfo->isActive(atm))
00687       {
00688         interimSec = timer.time(); 
00689         
00690         numbreak[i] = lwInfo->getUnSatCostWhenFlipped(atm, newClauses, newClauseWeights);
00691         bool initial = false;
00692         addNewClauses(initial);
00693         lwInfo->setActive(atm);
00694         //cout << "time taken for non-active (1) = "; Timer::printTime(cout, timer.time()-interimSec);
00695       }
00696       else
00697       {
00698         numbreak[i] = breakcost[atm];
00699       }
00700       //cout << endl;
00701     }
00702         
00703     switch(heuristic)
00704     {
00705       case RANDOM:
00706         choice = pickrandom(numbreak,size[tofix],tofix);
00707         break;
00708       case PRODUCTSUM:  
00709         choice = pickproductsum(numbreak,size[tofix],tofix);
00710         break;
00711       case RECIPROCAL:  
00712         choice = pickreciprocal(numbreak,size[tofix],tofix);
00713         break;
00714       case ADDITIVE:    
00715         choice = pickadditive(numbreak,size[tofix],tofix);
00716         break;
00717       case BEST:
00718         interimSec = timer.time();
00719         
00720         choice = pickbest(numbreak,size[tofix],tofix);
00721         
00722         //cout << "pickbest choice " << choice << endl;
00723         //cout << "\ttime taken for pickbest = "; Timer::printTime(cout, timer.time()-interimSec);
00724         //cout << endl;
00725         break;
00726       case EXPONENTIAL: 
00727         choice = pickexponential(numbreak,size[tofix],tofix);
00728         break;
00729       case TABU:        
00730         choice = picktabu(numbreak,size[tofix],tofix);
00731         break;
00732       default:          
00733         choice = pickbest(numbreak,size[tofix],tofix);
00734     }
00735         
00736     if (choice == NOVALUE)
00737       numnullflip++;
00738     else
00739     {
00740       int atm = abs(clause[tofix][choice]);
00741 
00742         // If chosen atom is deactivated or in block with evidence or fixed,
00743         // then continue to next flip (do not want to flip)
00744       if ((haveDeactivated && lwInfo->isDeactivated(atm)) ||
00745           (lwInfo->inBlockWithEvidence(atm)))
00746       {
00747         numnullflip++;
00748         return;
00749       }
00750     
00751       if(!lwInfo->isActive(atm))
00752       {
00753         interimSec = timer.time(); 
00754         
00755           // If atom is in a block, this is noted here in lwInfo
00756         lwInfo->getWalksatClausesWhenFlipped(atm, newClauses, newClauseWeights);
00757                  
00758         bool initial = false;
00759         addNewClauses(initial);
00760         lwInfo->setActive(atm);
00761         
00762         //cout << "\ttime taken for non-active (2) = "; Timer::printTime(cout, timer.time()-interimSec);
00763         //cout << endl;
00764       }
00765       else
00766       {
00767           // Have to check if in block and get other to flip
00768         if (lwInfo->inBlock(atm))
00769         {
00770           lwInfo->chooseOtherToFlip(atm, newClauses, newClauseWeights);
00771           bool initial = false;
00772           addNewClauses(initial);
00773         }
00774       }
00775       
00776       if (lwInfo->getInBlock())
00777         lwInfo->setActive(lwInfo->getOtherAtom());
00778 
00779       flipatom(atm);
00780       if (lwInfo->getInBlock())
00781       {
00782         flipatom(lwInfo->getOtherAtom());
00783       }
00784           
00785       lwInfo->flipVar(atm);
00786       if (lwInfo->getInBlock())
00787         lwInfo->flipVar(lwInfo->getOtherAtom());
00788 
00789         // Set back inBlock and other atom
00790       lwInfo->setInBlock(false);
00791       lwInfo->setOtherAtom(-1);
00792     }
00793   }
00794   //cout << "time taken for total flip = "; Timer::printTime(cout, timer.time()-begSec);
00795   //cout << endl;
00796 }
00797 
00798 
00799 void LazyWalksat::addNewClauses(bool initial)
00800 {
00801          //cout<<"adding new clauses.."<<endl;
00802   allClauses.append(newClauses);
00803   allClauseWeights.append(newClauseWeights);
00804   newClauses.clear();
00805   newClauseWeights.clear();
00806     
00807   int i;                        /* loop counter */
00808   int j;                        /* another loop counter */
00809         
00810   int lit;
00811   int litindex;
00812 
00813   // store the old number of clauses 
00814   int oldnumclause = numclause;
00815   int oldnumatom = numatom;
00816 
00817   numatom = lwInfo->getVarCount();
00818   numclause = allClauses.size();
00819         
00820   //allocate Memory if currently allocated memory is not sufficient.
00821   //We will allocate the memory to store twice the current number of clauses/atoms 
00822   //- so that do not have to do it again and again as any new clauses/atoms
00823   //appear
00824   /* allocate clause memory */
00825   if(clausemem < numclause )
00826   {
00827         //if memory is getting tight, then can not allocate 2 times
00828         if (2*numclause > clauseLimit)
00829           allocateClauseMemory(clauseLimit);
00830         else
00831           allocateClauseMemory(2*numclause);
00832   } 
00833 
00834   /* allocate atom memory */
00835   if(atommem < numatom)
00836   {
00837     allocateAtomMemory(2*numatom);
00838   }
00839 
00840   //initialize various structues for atoms
00841   for(int i = oldnumatom + 1; i < numatom + 1; i++)
00842   {
00843         atom[i] = lwInfo->getVarVal(i);
00844         initatom[i] = atom[i];
00845         lowatom[i] = atom[i];
00846         changed[i] = -BIG;
00847         breakcost[i] = 0;
00848   }
00849   
00850   for(int i = 2*oldnumatom + 1; i < 2*numatom + 1; i++)
00851   {
00852         numoccurence[i] = 0;
00853         newnumoccurence[i] = 0;
00854         occurencemem[i] = 0;
00855   }
00856 
00857   for(i = oldnumclause; i < numclause; i++)
00858   {
00859         size[i] = 0; 
00860         if (costexpected)
00861         {
00862           cost[i] = allClauseWeights[i];
00863         }
00864         else
00865         {
00866         /*the default cost of a clause violation is unit 1*/
00867       if (allClauseWeights[i] >= 0)
00868         cost[i] = 1;
00869       else
00870         cost[i] = -1;
00871     }
00872 
00873         if (clauseFreeStore < MAXLENGTH)
00874         {
00875           clauseStorePtr = clauseFSMgr->getStorePtr();
00876           clauseFreeStore = clauseFSMgr->getBlockSize();
00877         }
00878         clause[i] = clauseStorePtr;
00879         
00880         Array<int> *iclause = allClauses[i];
00881         for (j = 0; j < iclause->size(); j++)
00882         {
00883           size[i]++;
00884           if(size[i] > MAXLENGTH)
00885           {
00886                 printf("ERROR - clause too long\n");
00887                 exit(-1);
00888           }
00889           lit = (*iclause)[j]; 
00890 
00891           if(lit != 0)
00892           {
00893                 *(clauseStorePtr++) = lit; /* clause[i][size[i]] = j; */
00894                 clauseFreeStore--;
00895                 numliterals++;
00896             litindex = 2*abs(lit) - LWUtil::mySign(lit);
00897                 newnumoccurence[litindex]++;
00898           }
00899         }
00900   }
00901     
00902   //allocate memory to the literals which do not have sufficient
00903   //memory to store the list of all clauses they appear in 
00904   for(i = oldnumclause; i < numclause;i++)
00905   {
00906         for (j = 0; j <size[i]; j++)
00907         {
00908           lit = clause[i][j]; 
00909           litindex = 2*abs(lit) - LWUtil::mySign(lit);
00910           int totaloccurence = newnumoccurence[litindex] + numoccurence[litindex];
00911 
00912           if(occurencemem[litindex] < totaloccurence)
00913           {
00914             int tmpoccurencemem = 2*totaloccurence;
00915             if(atomFreeStore < tmpoccurencemem)
00916             {
00917                   atomStorePtr = atomFSMgr->getStorePtr();
00918                   atomFreeStore = atomFSMgr->getBlockSize();
00919                   //fprintf(stderr,"allocating memory...\n");
00920             }
00921                 
00922                 int *tmpoccurence = atomStorePtr;
00923                 atomFreeStore -= tmpoccurencemem;
00924                 atomStorePtr += tmpoccurencemem;
00925                 for(int k = 0; k < occurencemem[litindex]; k++)
00926                   tmpoccurence[k] = occurence[litindex][k];
00927                 occurencemem[litindex] = tmpoccurencemem;
00928                 occurence[litindex] = tmpoccurence;
00929                 //cout<<"occurencemem["<<litindex<<"] = "<<occurencemem[litindex]<<endl;
00930       }
00931         }
00932   }     
00933 
00934   for(i = oldnumclause; i < numclause; i++)
00935   {
00936         for(j = 0; j < size[i]; j++)
00937         {
00938           lit = clause[i][j];
00939           if(lit == 0)
00940             continue;
00941           litindex = 2*abs(lit) - LWUtil::mySign(lit);
00942           occurence[litindex][numoccurence[litindex]] = i;
00943           numoccurence[litindex]++;
00944           newnumoccurence[litindex]--;
00945         }
00946   }
00947   if(!initial)
00948     initializeBreakCost(oldnumclause);
00949 //cout<<"done adding new clauses.."<<endl;
00950 }
00951 
00952 // Deactivate atoms/clauses when memory is tight
00953 void LazyWalksat::trimClauses()
00954 {
00955   Array<int> idxOfDeactivated;
00956   if (!haveDeactivated)
00957   {
00958         haveDeactivated = true;
00959           // Remove only active atoms with zero delta-cost
00960         for (int i = 1; i <= numatom; i++)
00961           if (lwInfo->isActive(i) && breakcost[i] == 0)
00962                 idxOfDeactivated.append(i);       
00963   }
00964   else
00965   {
00966         int sumOfBreakCost = 0;
00967           // First: cost, second: index in breakcost
00968         Array<pair<int, int> > costs;
00969         for (int i = 1; i <= numatom; i++)
00970         {
00971           if (lwInfo->isActive(i))
00972           {
00973                 sumOfBreakCost += breakcost[i];
00974                 costs.append(pair<int, int>(breakcost[i], i));
00975           }
00976         }
00977 
00978         costs.quicksort();
00979 
00980         int sumOfDeactivated = 0;
00981         int numOfDeactivated = 0;
00982         for (int i = 0; i < costs.size(); i++)
00983         {
00984           sumOfDeactivated += costs[i].first;
00985                 // 10% of total weight
00986           if (sumOfDeactivated * 10 <= sumOfBreakCost)
00987           {
00988                 numOfDeactivated++;
00989                 idxOfDeactivated.append(costs[i].second);
00990           }
00991           else
00992                 break;
00993         }
00994   }
00995   
00996   clauseFSMgr->releaseAllStorePtr();
00997   atomFSMgr->releaseAllStorePtr();
00998  
00999   deleteClauseMemory();
01000   deleteAtomMemory();
01001                   
01002   delete clauseFSMgr;
01003   delete atomFSMgr;
01004 
01005   clauseStorePtr = NULL;
01006   clauseFreeStore = 0;
01007    
01008   atomStorePtr = NULL;
01009   atomFreeStore = 0;
01010    
01011   atomFSMgr = new FreeStoreManager(BLOCKSIZE);
01012   clauseFSMgr = new FreeStoreManager(BLOCKSIZE);
01013    
01014   numatom = 0;
01015   basenumatom = 0;  
01016   numclause = 0;
01017   numliterals = 0;
01018   numfalse = 0;
01019   costofnumfalse = 0;
01020   
01021   lwInfo->removeVars(idxOfDeactivated);
01022 
01023   for(int i = 0; i < newClauses.size(); i++)
01024     delete newClauses[i];
01025   newClauses.clear();
01026   newClauseWeights.clear();
01027 
01028   for(int i = 0; i < allClauses.size(); i++)
01029     delete allClauses[i];
01030   allClauses.clear();
01031   allClauseWeights.clear();
01032 
01033   lwInfo->getWalksatClauses(newClauses, newClauseWeights);
01034 
01035         //adding the clauses
01036   bool initial = true;
01037   addNewClauses(initial);
01038 }
01039   
01040 /* Initialize breakcost in the following: */
01041 void LazyWalksat::initializeBreakCost(int startclause)
01042 {
01043 //cout << "initbreakcost" << endl;
01044   int thetruelit = -1;
01045   for(int i = startclause; i < numclause; i++)
01046   {
01047     numtruelit[i] = 0;
01048         for(int j = 0; j < size[i]; j++)
01049         {
01050         // true literal
01051           if((clause[i][j] > 0) == atom[abs(clause[i][j])])
01052           {
01053                 numtruelit[i]++;
01054                 thetruelit = clause[i][j];
01055           }
01056     }
01057 
01058       // Unsatisfied positive-weighted clauses
01059     if(numtruelit[i] == 0 && cost[i] >= 0)
01060     {
01061           wherefalse[i] = numfalse;
01062           falseclause[numfalse] = i;
01063       ++numfalse;
01064           costofnumfalse += cost[i];
01065       if (highestcost == cost[i]) {eqhighest = true; numhighest++;}
01066     }
01067       // Satisfied negative-weighted clauses
01068     else if(numtruelit[i] > 0 && cost[i] < 0)
01069     {
01070       wherefalse[i] = numfalse;
01071       falseclause[numfalse] = i;
01072       ++numfalse;
01073       costofnumfalse += abs(cost[i]);
01074       if (highestcost == abs(cost[i])) {eqhighest = true; numhighest++;}
01075     }
01076       // Pos. clause satisfied by exactly one literal: note breakcost for that lit
01077     else if (numtruelit[i] == 1 && cost[i] >= 0)
01078     {
01079           breakcost[abs(thetruelit)] += cost[i];
01080         }
01081       // Neg. clause not satisfied: note breakcost for all lits
01082     else if (numtruelit[i] == 0 && cost[i] < 0)
01083     {
01084       for(int j = 0; j < size[i]; j++)
01085       {
01086         breakcost[abs(clause[i][j])] += abs(cost[i]);
01087       }
01088     }
01089   }
01090 //cout << "done initbreakcost" << endl;
01091 }
01092          
01093 
01094 void LazyWalksat::allocateClauseMemory(int allocCount)
01095 {
01096         //cout<<"Allocating Memory to Store "<<allocCount<<" Clauses.."<<endl;
01097   int **tmpclause = new int*[allocCount];
01098   int *tmpcost = new int[allocCount];
01099   int *tmpsize = new int[allocCount];
01100   
01101   int *tmpfalseclause = new int[allocCount];
01102   int *tmpwherefalse = new int[allocCount];
01103   int *tmpnumtruelit = new int[allocCount];
01104         
01105   for(int i = 0; i < clausemem; i++)
01106   {
01107     tmpclause[i] = clause[i];
01108     tmpcost[i] = cost[i];
01109     tmpsize[i] = size[i];
01110                 
01111     tmpfalseclause[i] = falseclause[i];
01112     tmpwherefalse[i] = wherefalse[i];
01113     tmpnumtruelit[i] = numtruelit[i];
01114   }
01115   
01116   deleteClauseMemory();
01117     
01118   clause = tmpclause;
01119   cost = tmpcost;
01120   size = tmpsize;
01121         
01122   falseclause = tmpfalseclause;
01123   wherefalse = tmpwherefalse;
01124   numtruelit = tmpnumtruelit;
01125         
01126   clausemem = allocCount;
01127 }
01128 
01129 
01130 void LazyWalksat::allocateAtomMemory(int allocCount)
01131 {       
01132         //cout<<"Allocating Memory to Store "<<allocCount<<" Atoms.."<<endl;    
01133   int **tmpoccurence = new int*[2*allocCount+1];        
01134   int *tmpnumoccurence = new int[2*allocCount+1];       
01135   int *tmpnewnumoccurence = new int[2*allocCount+1];    
01136   int *tmpoccurencemem  = new int[2*allocCount+1];      
01137         
01138   int *tmpatom = new int[allocCount+1]; 
01139   int *tmpinitatom = new int[allocCount+1];     
01140   int *tmplowatom = new int[allocCount+1];      
01141   int *tmpchanged = new int[allocCount+1];      
01142   int *tmpbreakcost = new int[allocCount+1];    
01143 
01144   if(atommem > 0)
01145   {
01146     for(int i = 0; i < 2*atommem + 1; i++)
01147     {
01148       tmpoccurence[i] = occurence[i];
01149       tmpnumoccurence[i] = numoccurence[i];
01150       tmpnewnumoccurence[i] = newnumoccurence[i];
01151       tmpoccurencemem[i] = occurencemem[i];
01152     }
01153 
01154     for(int i = 0; i < atommem + 1; i++)
01155     {
01156       tmpatom[i] = atom[i];
01157           tmpinitatom[i] = initatom[i];
01158           tmplowatom[i] = lowatom[i];
01159           tmpchanged[i] = changed[i];
01160           tmpbreakcost[i] = breakcost[i];
01161         }
01162   }
01163 
01164   deleteAtomMemory();
01165     
01166   occurence = tmpoccurence;
01167   numoccurence = tmpnumoccurence;
01168   newnumoccurence = tmpnewnumoccurence;
01169   occurencemem = tmpoccurencemem;
01170         
01171   atom = tmpatom;
01172   initatom = tmpinitatom;
01173   lowatom = tmplowatom;
01174   changed = tmpchanged;
01175   breakcost = tmpbreakcost;
01176         
01177   atommem = allocCount;
01178 }
01179 
01180 
01181 void LazyWalksat::deleteClauseMemory()
01182 {
01183   if(clausemem == 0)
01184     return;
01185 
01186   delete [] clause;
01187   delete [] cost;
01188   delete [] size;
01189   delete [] falseclause;
01190   delete [] wherefalse;
01191   delete [] numtruelit;
01192   
01193   clausemem = 0;
01194 }
01195 
01196 void LazyWalksat::deleteAtomMemory()
01197 {    
01198   if(atommem == 0)
01199     return;
01200 
01201   delete [] occurence;
01202   delete [] numoccurence;
01203   delete [] newnumoccurence;
01204   delete [] occurencemem;
01205         
01206   delete [] atom;
01207   delete [] initatom;
01208   delete [] lowatom;
01209   delete [] changed;
01210   delete [] breakcost;
01211 
01212   atommem = 0;
01213 }
01214 
01215 
01216 void LazyWalksat::flipatom(int toflip)
01217 {
01218   int i, j;                     /* loop counter */
01219   int litindex;
01220   register int cli;
01221   register int lit;
01222   int numocc;
01223   register int sz;
01224   register int * litptr;
01225   int * occptr;
01226 
01227   changed[toflip] = numflip;
01228   atom[toflip] = 1 - atom[toflip];
01229 
01230   int sign, oppsign;
01231         
01232   sign = atom[toflip];
01233     //oppsign = 1 - sign;
01234   oppsign = sign ^ 1;
01235     
01236   litindex = 2*toflip - oppsign;
01237   numocc = numoccurence[litindex];
01238   occptr = occurence[litindex];
01239     
01240   for(i = 0; i < numocc; i++)
01241   {
01242         cli = *(occptr++);
01243         
01244       // Neg. clause
01245     if (cost[cli] < 0)
01246     {
01247         // Became unsatisfied: Decrease num. of false clauses
01248       if (--numtruelit[cli] == 0)
01249       {
01250         numfalse--;
01251         costofnumfalse -= abs(cost[cli]);
01252         falseclause[wherefalse[cli]] = falseclause[numfalse];
01253         wherefalse[falseclause[numfalse]] = wherefalse[cli];
01254           
01255         if (abs(cost[cli]) == highestcost)
01256           { numhighest--; if (numhighest == 0) eqhighest = false; }
01257               
01258           /* Increment all atoms' breakcount */
01259         sz = size[cli];
01260         litptr = clause[cli];
01261         for(j = 0; j < sz; j++)
01262         {
01263           lit = *(litptr++);
01264           breakcost[abs(lit)] += abs(cost[cli]);
01265         }
01266       }
01267     }
01268       // Pos. clause
01269     else
01270     {
01271       if (--numtruelit[cli] == 0)
01272       {
01273         falseclause[numfalse] = cli;
01274         wherefalse[cli] = numfalse;
01275         numfalse++;
01276         costofnumfalse += cost[cli];
01277               // Decrement toflip's breakcost
01278         breakcost[toflip] -= cost[cli];
01279         if (cost[cli] == highestcost) { eqhighest = true; numhighest++; }
01280       }
01281       else if (numtruelit[cli] == 1)
01282       {
01283           /* Find the lit in this clause that makes it true, and inc its breakcount */
01284         sz = size[cli];
01285         litptr = clause[cli];
01286         for (j = 0; j < sz; j++)
01287         {
01288             /* lit = clause[cli][j]; */
01289           lit = *(litptr++);
01290           if((lit > 0) == atom[abs(lit)])
01291           {
01292             breakcost[abs(lit)] += cost[cli];
01293             break;
01294           }
01295         }
01296       }
01297     }
01298   }
01299    
01300   litindex = 2*toflip - sign;
01301   numocc = numoccurence[litindex];
01302   occptr = occurence[litindex];
01303         
01304   for(i = 0; i < numocc; i++)
01305   {
01306         cli = *(occptr++);
01307 
01308       // Neg. clause
01309     if (cost[cli] < 0)
01310     {
01311         // Became satisfied: increment num. of false clauses
01312       if (++numtruelit[cli] == 1)
01313       {
01314         wherefalse[cli] = numfalse;
01315         falseclause[numfalse] = cli;
01316         ++numfalse;
01317         costofnumfalse += abs(cost[cli]);
01318         if (highestcost == abs(cost[cli])) {eqhighest = true; numhighest++;}
01319 
01320           /* Decrement all atoms' breakcount */
01321         sz = size[cli];
01322         litptr = clause[cli];
01323         for(j = 0; j < sz; j++)
01324         {
01325           lit = *(litptr++);
01326           breakcost[abs(lit)] -= abs(cost[cli]);
01327         }
01328       }
01329     }
01330       // Pos. clause
01331     else
01332     {
01333       if (++numtruelit[cli] == 1)
01334       {
01335         numfalse--;
01336         costofnumfalse -= cost[cli];
01337         falseclause[wherefalse[cli]] = falseclause[numfalse];
01338         wherefalse[falseclause[numfalse]] = wherefalse[cli];
01339               
01340               /* Increment toflip's breakcount */
01341         breakcost[toflip] += cost[cli];
01342         if (cost[cli] == highestcost)
01343           { numhighest--; if (numhighest==0) eqhighest = false; }
01344       }
01345       else if (numtruelit[cli] == 2)
01346       {
01347               /* Find the lit in this clause other than toflip that makes it true,
01348                      and decrement its breakcount */
01349         sz = size[cli];
01350         litptr = clause[cli];
01351         for (j = 0; j < sz; j++)
01352         {
01353             /* lit = clause[cli][j]; */
01354           lit = *(litptr++);
01355           if(((lit > 0) == atom[abs(lit)]) &&
01356              (toflip != abs(lit)) )
01357           {
01358             breakcost[abs(lit)] -= cost[cli];
01359             break;
01360           }
01361         }
01362       }
01363     }
01364   }
01365 }
01366 
01367 
01368 long LazyWalksat::super(int i)
01369 {
01370   long power;
01371   int k;
01372 
01373   if (i <= 0)
01374   {
01375         fprintf(stderr, "bad argument super(%d)\n", i);
01376         exit(1);
01377   }
01378     /* let 2^k be the least power of 2 >= (i+1) */
01379   k = 1;
01380   power = 2;
01381   while (power < (i+1))
01382   {
01383         k += 1;
01384         power *= 2;
01385   }
01386   if (power == (i+1)) return (power/2);
01387   return (super(i - (power/2) + 1));
01388 }
01389 
01390 
01391 void LazyWalksat::scanone(int argc, char *argv[], int i, int *varptr)
01392 {
01393   if (i >= argc || sscanf(argv[i],"%i",varptr)!=1)
01394   {
01395         fprintf(stderr, "Bad argument %s\n", i<argc ? argv[i] : argv[argc-1]);
01396         exit(-1);
01397   }
01398 }
01399 
01400 void LazyWalksat::print_false_clauses_cost(long int lowbad)
01401 {
01402   int i, j;
01403   bool bad;
01404   int lit, sign;
01405 
01406   printf("Unsatisfied pos. clauses and satisfied neg. clauses:\n");
01407   for (i = 0; i < numclause; i++)
01408   {
01409       // Neg. clause
01410     if (cost[i] < 0)
01411       bad = false;
01412       // Pos. clause
01413     else
01414       bad = true;
01415     
01416         for (j = 0; j < size[i]; j++)
01417     {
01418           lit = clause[i][j];
01419           sign = lit > 0 ? 1 : 0;
01420 
01421           if ( lowatom[abs(lit)] == sign )
01422       {
01423           // Neg. clause
01424         if (cost[i] < 0)
01425           bad = true;
01426           // Pos. clause
01427         else
01428           bad = false;
01429         break;
01430           }
01431         }
01432         
01433     if (bad)
01434     {
01435           printf("Cost %i ", cost[i]);
01436           for (j = 0; j < size[i]; j++)
01437       {
01438                 printf("%d ", clause[i][j]);
01439           }
01440           printf("0\n");
01441         }
01442   }
01443   printf("End unsatisfied pos. clauses and satisfied neg. clauses\n");
01444 }
01445 
01446 
01447 int LazyWalksat::countunsat(void)
01448 {
01449   int i, j, unsat, lit, sign;
01450   bool bad;
01451 
01452   unsat = 0;
01453   for (i = 0; i < numclause; i++)
01454   {
01455       // Neg. clause
01456     if (cost[i] < 0)
01457       bad = false;
01458       // Pos. clause
01459     else
01460       bad = true;
01461 
01462         for (j = 0; j < size[i]; j++)
01463         {
01464           lit = clause[i][j];
01465           sign = lit > 0 ? 1 : 0;
01466           if ( atom[abs(lit)] == sign )
01467           {
01468           // Neg. clause
01469         if (cost[i] < 0)
01470           bad = true;
01471           // Pos. clause
01472         else
01473           bad = false;
01474         break;
01475           }
01476         }
01477         if (bad) unsat++;
01478   }
01479   return unsat;
01480 }
01481 
01482 void LazyWalksat::countlowunsatcost(int * unsatcostptr, int * worstcostptr)
01483 {
01484   int i, j, lit, sign, unsatcost, worstcost;
01485   bool bad;
01486 
01487   unsatcost = 0;
01488   worstcost = 0;
01489   for (i = 0; i < numclause; i++)
01490   {
01491       // Neg. clause
01492     if (cost[i] < 0)
01493       bad = false;
01494       // Pos. clause
01495     else
01496       bad = true;
01497 
01498         for (j = 0; j < size[i]; j++)
01499         {
01500           lit = clause[i][j];
01501           sign = lit > 0 ? 1 : 0;
01502           if ( lowatom[abs(lit)] == sign )
01503           {
01504           // Neg. clause
01505         if (cost[i] < 0)
01506           bad = true;
01507           // Pos. clause
01508         else
01509           bad = false;
01510         break;
01511           }
01512         }
01513         if (bad)
01514         {
01515           unsatcost += abs(cost[i]);
01516           if (abs(cost[i]) > worstcost) worstcost = abs(cost[i]);
01517         }
01518   }
01519   * unsatcostptr = unsatcost;
01520   * worstcostptr = worstcost;
01521   return;
01522 }
01523 
01524 
01525 double LazyWalksat::elapsed_seconds(void)
01526 {
01527   double answer;
01528 
01529   static struct rusage prog_rusage;
01530   static long prev_rusage_seconds = 0;
01531   static long prev_rusage_micro_seconds = 0;
01532 
01533   getrusage(0, &prog_rusage);
01534   answer = (double)(prog_rusage.ru_utime.tv_sec - prev_rusage_seconds)
01535                 + ((double)(prog_rusage.ru_utime.tv_usec - prev_rusage_micro_seconds)) / 
01536            1000000.0 ;
01537   prev_rusage_seconds = prog_rusage.ru_utime.tv_sec ;
01538   prev_rusage_micro_seconds = prog_rusage.ru_utime.tv_usec ;
01539   return answer;
01540 }
01541 
01542 
01543 void LazyWalksat::print_low_assign(long int lowbad)
01544 {
01545   int i, j;
01546 
01547   cout<<"Begin assign with lowest # bad = "<<lowbad<<" (atoms assigned true)\n";
01548   j = 1;
01549   for (i = 1; i <= numatom; i++)
01550   {
01551         if (lowatom[i]>0)
01552     {
01553           printf(" %d", i);
01554           if (j++ % 10 == 0) printf("\n");
01555         }
01556   }
01557   if ((j-1) % 10 != 0) printf("\n");
01558   printf("End assign\n");
01559 }
01560 
01561 void LazyWalksat::save_low_assign(void)
01562 {
01563   for (int i = 1; i <= numatom; i++)
01564     lowatom[i] = atom[i];
01565 }
01566 
01567 
01568 void LazyWalksat::printClause(int cl)
01569 {
01570   cout<<"(";
01571   for(int i = 0; i < size[cl]; i++)
01572   {    
01573         cout << clause[cl][i];
01574     if (i != size[cl] - 1)
01575     cout <<",";
01576   }
01577   cout<<")"<<endl;
01578 }
01579 
01580 int LazyWalksat::selecthigh(int high)
01581 {
01582   //cout<<"inside select high.."<<endl;
01583   int counter = 0;
01584   int i = 0;
01585   while ((i < numfalse) && (counter < high))
01586   {
01587     if (abs(cost[falseclause[i]]) == highestcost)
01588       counter++;
01589     i++;
01590   }
01591  /* fprintf(stderr, "The cost of the selected clause %i\n", cost[false[i-1]]);*/
01592   //cout<<"successful in select high.."<<endl;
01593   return(falseclause[i-1]);
01594 }
01595    
01596 
01597 int LazyWalksat::pickrandom(int *numbreak, int clausesize, int tofix)
01598         /* returns a random number */
01599 {
01600   return(random()%clausesize);
01601 }
01602 
01603 int LazyWalksat::pickproductsum(int *numbreak, int clausesize, int tofix)
01604         /* weights each possibility by the */
01605         /* product of the product and sum of everything else */
01606 {
01607   int i;                             /* a loop counter */
01608   int weight[MAXLENGTH];             /* weights of each possibility */
01609   int tochange;                      /* value to return */
01610   int totalproduct = 1;              /* product of all numbreaks */
01611   int totalsum = 0;                  /* sum of all numbreaks */
01612 
01613   if(clausesize == 1)
01614         return(0);
01615   if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
01616         return(tochange);
01617   for(i = 0; i < clausesize; i++)
01618   {
01619         totalproduct *= numbreak[i];
01620         totalsum += numbreak[i];
01621   }
01622   for(i = 0; i < clausesize; i++)
01623   {
01624         weight[i] = (totalproduct/numbreak[i])*
01625                 (totalsum-numbreak[i]);
01626   }
01627   return(pickweight(weight,clausesize));
01628 }
01629 
01630 int LazyWalksat::pickreciprocal(int *numbreak, int clausesize, int tofix)
01631         /* weights each possibility by its reciprocal*/
01632 {
01633   int i;                             /* a loop counter */
01634   int weight[MAXLENGTH];             /* weights of each possibility */
01635   int tochange;                      /* value to return */
01636   int totalproduct = 1;              /* product of all numbreaks */
01637 
01638   if(clausesize == 1)
01639         return(0);
01640   if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
01641         return(tochange);
01642   for(i = 0;i < clausesize;i++)
01643         totalproduct *= numbreak[i];
01644   for(i = 0;i < clausesize;i++)
01645         weight[i] = (totalproduct/numbreak[i]);
01646   return(pickweight(weight,clausesize));
01647 }
01648 
01649 int LazyWalksat::pickadditive(int *numbreak, int clausesize, int tofix)
01650         /* weights each possibility by the sum of the others */
01651 {
01652   int i;                             /* a loop counter */
01653   int weight[MAXLENGTH];             /* weights of each possibility */
01654   int tochange;                      /* value to return */
01655   int totalsum = 0;                  /* sum of all numbreaks */
01656 
01657   if(clausesize == 1)
01658         return(0);
01659   if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
01660         return(tochange);
01661   for(i = 0; i < clausesize;i++)
01662         totalsum += numbreak[i];
01663   for(i = 0; i < clausesize;i++)
01664         weight[i] = (totalsum-numbreak[i]);
01665   return(pickweight(weight,clausesize));
01666 }
01667 
01668 int LazyWalksat::pickbest(int *numbreak, int clausesize, int tofix)
01669 {
01670   int i;                        /* a loop counter */
01671   int best[MAXLENGTH];  /* best possibility so far */
01672   int numbest;          /* how many are tied for best */
01673   int bestvalue;                /* best value so far */
01674 
01675   numbest = 0;
01676   bestvalue = INT_MAX;
01677 
01678   for (i = 0; i < clausesize; i++)
01679   {
01680     if (numbreak[i] <= bestvalue)
01681         {
01682           if (numbreak[i] < bestvalue) numbest = 0;
01683           bestvalue = numbreak[i];
01684           best[numbest++] = i;
01685         }
01686   }
01687         
01688   if (bestvalue > 0 && (random()%denominator < numerator))
01689   {
01690         if (!hard || abs(cost[tofix]) >= highestcost)
01691           return(random()%clausesize); /* allow random breaks of hard clauses */
01692 
01693           /* only do a random walk breaking non-hard clauses */
01694         numbest = 0;
01695         for (i = 0; i < clausesize; i++)
01696         {
01697           if (numbreak[i] < highestcost)
01698           {
01699         best[numbest++] = i;
01700           }
01701         }
01702           /* if (numbest==0) { fprintf(stderr, "Wff is not feasible!\n"); exit(1); } */
01703         if (numbest == 0) { return(random()%clausesize); }
01704   }
01705     
01706   if (numbest == 1) return best[0];
01707     
01708     //Added this to avoid a crash when numbest is 0 in (random()%numbest)
01709   if (numbest == 0) { return(random()%clausesize); }
01710         
01711   return(best[random()%numbest]);
01712 }
01713 
01714 
01715 int LazyWalksat::picktabu(int *numbreak,int clausesize, int tofix)
01716 {
01717   int i;                        /* a loop counter */
01718   int best[MAXLENGTH];  /* best possibility so far */
01719   int numbest;          /* how many are tied for best */
01720   int bestvalue;                /* best value so far */
01721 
01722   numbest = 0;
01723   bestvalue = BIG;
01724 
01725   if (numerator>0 && (random()%denominator < numerator))
01726   {
01727         for (i = 0; i < clausesize; i++)
01728     {
01729           if ((tabu_length < numflip - changed[abs(clause[tofix][i])]) ||
01730                   numbreak[i] == 0)
01731       {
01732                 if (numbreak[i]==0) numbest=0;
01733                 best[numbest++] = i;
01734           }
01735         }
01736   }
01737   else
01738   {
01739         for (i = 0; i < clausesize; i++)
01740     {
01741           if (numbreak[i] <= bestvalue && 
01742                   ((tabu_length < numflip - changed[abs(clause[tofix][i])]) ||
01743                   numbreak[i] == 0))
01744       {
01745                 if (numbreak[i] < bestvalue) numbest=0;
01746                 bestvalue = numbreak[i];
01747                 best[numbest++] = i;
01748           }
01749         }
01750   }
01751     
01752   if (numbest == 0) return NOVALUE;
01753   if (numbest == 1) return best[0];
01754   return (best[random()%numbest]);
01755 }
01756 
01757 int LazyWalksat::pickexponential(int *numbreak,int clausesize, int tofix)
01758 {
01759   int i;                             /* a loop counter */
01760   int weight[MAXLENGTH];             /* weights of each possibility */
01761   int tochange;                      /* value to return */
01762 
01763   if(clausesize == 1)
01764         return(0);
01765   if((tochange = pickzero(numbreak,clausesize)) != NOVALUE)
01766         return(tochange);
01767   for(i = 0; i < clausesize; i++)
01768         weight[i] = 2*2*2*2*2*2*2*2*2*2*2*2*2*2;
01769   for(i = 0; i < clausesize; i++)
01770   {
01771         weight[i] >>= numbreak[i]; /* weight[i] = weight[i]/(2^numbreak[i]) */
01772   }
01773 
01774   return(pickweight(weight,clausesize));
01775 }
01776 
01777 int LazyWalksat::pickzero(int *numbreak,int clausesize)
01778 {
01779   int i;                /* loop counter */
01780   int numzero = 0;      /* number of zeros so far */
01781   int select;           /* random number */
01782 
01783   for(i = 0; i < clausesize; i++)
01784   {
01785         if(numbreak[i] == 0)
01786         numzero++;
01787   }
01788   if(numzero == 0)
01789         return(NOVALUE);
01790   select = random()%numzero;
01791   for(i = 0;select >= 0; i++)
01792   {
01793         if(numbreak[i] == 0)
01794         select--;
01795   }
01796   return(i-1);
01797 }
01798 
01799 int LazyWalksat::pickweight(int *weight,int clausesize)
01800 {
01801   int i;                /* loop counter */
01802   int total = 0;        /* sum of weights */
01803   int select;           /* random number less than total */
01804   int subtotal = 0;
01805 
01806   for(i = 0; i < clausesize; i++)
01807         total += weight[i];
01808   if(total == 0)
01809         return(random()%clausesize);
01810   select = random()%total;
01811   for(i = 0; subtotal <= select; i++)
01812         subtotal += weight[i];
01813   return(i-1);
01814 }
01815 
01816 /* Simulated Annealing */
01817 bool LazyWalksat::simAnnealing()
01818 {
01819     // No non-evidence atoms left
01820   if (lwInfo->getNumDBAtoms() == 0)
01821   {
01822     numnullflip++;
01823     return true;
01824   }
01825     // index of atom chosen to flip
01826   int toflip = -1;
01827     // cost change caused by flipping this atom
01828   int change;
01829 
01830   if (numfalse == 0 || (random() % 100 < saRatio && !latesa))
01831   {
01832     bool initial = false;
01833       // Activate random non-evid. atom
01834     if (lwInfo->activateRandomAtom(newClauses, newClauseWeights, toflip))
01835       addNewClauses(initial);
01836       // If chosen atom is deactivated or in block with evidence
01837       // or fixed, then continue to next flip
01838     if ((haveDeactivated && lwInfo->isDeactivated(toflip)) ||
01839         (lwInfo->inBlockWithEvidence(toflip)))
01840     {
01841       numnullflip++;
01842       return true;
01843     }
01844 
01845       //interfacing with external world - if this atom is not active,
01846       //need to get the cost of clauses which would become unsatisfied
01847       //by flipping it. 
01848     if(!lwInfo->isActive(toflip))
01849     {
01850       change = -lwInfo->getUnSatCostWhenFlipped(toflip, newClauses, newClauseWeights);
01851       bool initial = false;
01852       addNewClauses(initial);
01853       lwInfo->setActive(toflip);
01854     }
01855     else
01856     {
01857       change = -breakcost[toflip];
01858     }
01859 
01860       // If change is not neg. or randomly according
01861       // to temperature, then flip the atom
01862     if (change >= 0 ||
01863         random() <= exp(change / (temperature / 100.0)) * RAND_MAX)
01864     {
01865       if(!lwInfo->isActive(toflip))
01866       {
01867         lwInfo->getWalksatClausesWhenFlipped(toflip, newClauses, newClauseWeights);
01868          
01869         bool initial = false;
01870         addNewClauses(initial);
01871         lwInfo->setActive(toflip);
01872       }
01873       else
01874       {
01875           // Have to check if in block and get other to flip
01876         if (lwInfo->inBlock(toflip))
01877         {
01878           lwInfo->chooseOtherToFlip(toflip, newClauses, newClauseWeights);
01879           bool initial = false;
01880           addNewClauses(initial);
01881         }
01882       }
01883 
01884       if (lwInfo->getInBlock())
01885         lwInfo->setActive(lwInfo->getOtherAtom());
01886     
01887       flipatom(toflip);
01888       if (lwInfo->getInBlock())
01889       {
01890         flipatom(lwInfo->getOtherAtom());
01891       }
01892           
01893       lwInfo->flipVar(toflip);
01894       if (lwInfo->getInBlock())
01895         lwInfo->flipVar(lwInfo->getOtherAtom());
01896 
01897         // Set back inBlock and other atom
01898       lwInfo->setInBlock(false);
01899       lwInfo->setOtherAtom(-1);
01900     }
01901     else numnullflip++;
01902 
01903     return true;
01904   }
01905   else
01906     return false;
01907 }
01908 
01909 void LazyWalksat::undoFixedAtoms()
01910 {
01911   //Timer timer;
01912   //double begSec = timer.time(); 
01913 
01914   for (int i = 1; i < maxFixedAtoms; i++)
01915   {
01916     if (fixedAtoms_[i])
01917     {
01918       lwInfo->setEvidence(i, false);
01919       lwInfo->incrementNumDBAtoms();
01920       fixedAtoms_[i] = false;
01921     }
01922   }
01923 
01924   //cout << "time taken for clearing fixed atoms = "; Timer::printTime(cout, timer.time()-begSec);
01925   //cout << endl;
01926 }
01927 
01928 /* 
01929  * Fixes atoms using unit propagation on active clauses.
01930  * Fixed atoms are stored in fixedAtoms_ and set as evidence in the DB.
01931  */
01932 void LazyWalksat::initFixedAtoms(Array<Array<int> *> &clauses,
01933                                  Array<int> &clauseWeights)
01934 {
01935   //cout << "Clauses before UP: " << clauses.size() << endl;
01936   //cout << "Clauseweights before UP: " << clauseWeights.size() << endl;
01937   //cout << "Performing unit propagation ..." << endl;
01938   //Timer timer;
01939   //double begSec = timer.time(); 
01940 
01941   bool done = false;
01942   while (!done)
01943   {
01944     done = true;
01945       // For each clause, fix truth value if unit clause
01946       // after trimming evidence
01947     for (int i = 0; i < clauses.size(); i++)
01948     {
01949       Array<int>* clause = clauses[i];
01950 
01951         // All atoms could have been removed in prev. iteration
01952       if (clause->size() < 1)
01953       {
01954         //delete clauses[i];
01955         //clauses[i] = NULL;
01956         delete clauses.removeItemFastDisorder(i);
01957         clauseWeights.removeItemFastDisorder(i);
01958         i--;
01959         continue;
01960       }
01961 
01962         // Neg. clauses: all atoms fixed to false
01963       if (clauseWeights[i] < 0)
01964       {
01965         for (int j = 0; j < clause->size(); j++)
01966         {
01967           int atm = (*clause)[j];
01968             // If not already fixed, fix it
01969           if (!fixedAtoms_[abs(atm)])
01970           {
01971             lwInfo->setInactive(abs(atm));
01972             lwInfo->setEvidence(abs(atm), true);
01973             lwInfo->decrementNumDBAtoms();
01974             done = false;
01975             fixedAtoms_[abs(atm)] = true;
01976               // Neg. clause, neg. atom: set to true
01977             if (atm < 0)
01978             {
01979               lwInfo->setVarVal(abs(atm), true);
01980             }
01981               // Neg. clause, pos. atom: set to false
01982             else if (atm > 0)
01983             {
01984               lwInfo->setVarVal(abs(atm), false);
01985             }
01986           }
01987         }
01988         
01989         delete clauses.removeItemFastDisorder(i);
01990         clauseWeights.removeItemFastDisorder(i);
01991         i--;
01992         continue;
01993       }
01994 
01995         // Unit clause
01996       if (clause->size() == 1)
01997       {
01998         int atm = (*clause)[0];
01999 
02000           // If not already fixed, fix it
02001         if (!fixedAtoms_[abs(atm)])
02002         {
02003           lwInfo->setInactive(abs(atm));
02004           lwInfo->setEvidence(abs(atm), true);
02005           lwInfo->decrementNumDBAtoms();
02006           done = false;
02007           //fixedAtoms_.append(abs(atm));
02008           fixedAtoms_[abs(atm)] = true;
02009             // Pos. clause, pos. atom: set to true
02010             // Neg. clause, neg. atom: set to true
02011           if ((clauseWeights[i] > 0 && atm > 0) ||
02012               (clauseWeights[i] < 0 && atm < 0))
02013           {
02014             lwInfo->setVarVal(abs(atm), true);
02015           }
02016             // Pos. clause, neg. atom: set to false
02017             // Neg. clause, pos. atom: set to false
02018           else if ((clauseWeights[i] > 0 && atm < 0) ||
02019                    (clauseWeights[i] < 0 && atm > 0))
02020           {
02021             lwInfo->setVarVal(abs(atm), false);          
02022           }
02023         }
02024         
02025         delete clauses.removeItemFastDisorder(i);
02026         clauseWeights.removeItemFastDisorder(i);
02027         i--;
02028 //cout << "time taken for fixing unit clause = "; Timer::printTime(cout, timer.time()-begSec);
02029 //cout << endl;
02030         continue;
02031       }
02032       
02033         // Clause with 2+ atoms: try to trim evidence
02034       for (int j = 0; j < clause->size(); j++)
02035       {
02036         int atm = (*clause)[j];
02037         if (lwInfo->getEvidence(abs(atm)))
02038         {
02039           bool sense = (atm > 0);
02040           TruthValue tv = lwInfo->getVarVal(abs(atm)) ? TRUE : FALSE;
02041             // True evidence
02042           if (Database::sameTruthValueAndSense(tv, sense))
02043           {
02044               // Pos. clause: clause is satisfied and is removed
02045               // Neg. clause: clause can not be satisfied: remove it
02046             delete clauses.removeItemFastDisorder(i);
02047             clauseWeights.removeItemFastDisorder(i);
02048             i--;
02049             break;
02050           }
02051             // False evidence: remove atom from clause
02052           else
02053           {          
02054             clause->removeItemFastDisorder(j);
02055             j--;
02056             done = false;
02057           }
02058         }
02059 //cout << "time taken for trimming evidence = "; Timer::printTime(cout, timer.time()-begSec);
02060 //cout << endl;
02061         
02062       }
02063     }
02064   }
02065 //cout << "time taken for UP = "; Timer::printTime(cout, timer.time()-begSec);
02066 //cout << endl;
02067 
02068   //cout << "Clauses after UP: " << clauses.size() << endl;
02069   //cout << "Clauseweights after UP: " << clauseWeights.size() << endl;
02070   //cout << "Fixed atoms: " << fixedAtoms_.size() << endl;
02071   //cout << "Num. DB atoms: " << lwInfo->getNumDBAtoms() << endl;
02072 }

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