lazysat.cpp

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

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