00001
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
00033
00034
00035 clausemem = 0;
00036 atommem = 0;
00037
00038
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
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
00094 bool LazyWalksat::sample(const MaxWalksatParams* const & mwsParams,
00095 const SampleSatParams& sampleSatParams,
00096 const bool& initial)
00097 {
00098
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
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
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
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
00143 int base_cutoff = 100000;
00144 bool printonlysol = false;
00145 bool printfalse = false;
00146 bool printlow = true;
00147 int printtrace = 1000;
00148
00149 long int totalflip = 0;
00150 int numtry = 0;
00151 int numsuccesstry = 0;
00152 int numsol = numSolutions;
00153 int seed;
00154 struct timeval tv;
00155 struct timezone tzp;
00156 double setuptime;
00157 double expertime;
00158 double totaltime;
00159
00160 long int lowbad;
00161 long int lowcost;
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;
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
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
00195 if (memLimit > 0)
00196 {
00197
00198
00199
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
00204 clauseLimit = ((memLimit/2) / clauseSize) * 1024;
00205
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
00222
00223
00224
00225
00226
00227
00228
00229 resetSampleSat();
00230
00231 lwInfo->selectClauses(supersetClauses_, newClauses,
00232 newClauseWeights);
00233
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
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
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) )
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
00310 if (numclause > clauseLimit)
00311 {
00312 trimClauses();
00313 initrun();
00314 lowbad = numfalse;
00315 lowcost = costofnumfalse;
00316 save_low_assign();
00317 continue;
00318 }
00319
00320
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
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
00379 lwInfo->setVarVals(lowatom);
00380
00381
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
00416 for(int atom = basenumatom + 1; atom <= numatom; atom++)
00417 {
00418 lwInfo->setVarVal(atom, false);
00419 lwInfo->setInactive(atom);
00420 }
00421
00422
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
00436
00437
00438
00445 void LazyWalksat::init()
00446 {
00447 Timer timer;
00448 double begSec = timer.time();
00449
00450
00451 highestcost = BIG;
00452
00453 numclause = 0;
00454 numatom = 0;
00455 numliterals = 0;
00456
00457
00458
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
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
00510 if (sample)
00511 {
00512 lwInfo->getSupersetClauses(supersetClauses_);
00513
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
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
00544 void LazyWalksat::initrun()
00545 {
00546
00547 int newval;
00548 numfalse = 0;
00549 costofnumfalse = 0;
00550 eqhighest = false;
00551 numhighest = 0;
00552
00553
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
00580
00581 }
00582
00583
00584 void LazyWalksat::fix(int tofix)
00585 {
00586 Timer timer;
00587
00588 double interimSec;
00589
00590
00591 if (cost[tofix] < 0)
00592 {
00593
00594 if (numtruelit[tofix] > 0)
00595 {
00596 for (int i = 0; i < size[tofix]; i++)
00597 {
00598 int atm = abs(clause[tofix][i]);
00599
00600 if((clause[tofix][i] > 0) == atom[atm])
00601 {
00602
00603
00604
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
00614 lwInfo->getWalksatClausesWhenFlipped(atm, newClauses, newClauseWeights);
00615
00616 bool initial = false;
00617 addNewClauses(initial);
00618 lwInfo->setActive(atm);
00619
00620
00621 }
00622 else
00623 {
00624
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
00647 lwInfo->setInBlock(false);
00648 lwInfo->setOtherAtom(-1);
00649
00650
00651 }
00652 }
00653 }
00654
00655 else
00656 {
00657 numnullflip++;
00658 }
00659 }
00660
00661 else
00662 {
00663
00664 int numbreak[MAXLENGTH];
00665
00666 int i;
00667 int choice;
00668
00669 for(i = 0; i < size[tofix]; i++)
00670 {
00671
00672 int atm = abs(clause[tofix][i]);
00673
00674
00675
00676 if ((haveDeactivated && lwInfo->isDeactivated(atm)) ||
00677 (lwInfo->inBlockWithEvidence(atm)))
00678 {
00679 numbreak[i] = INT_MAX;
00680 continue;
00681 }
00682
00683
00684
00685
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
00695 }
00696 else
00697 {
00698 numbreak[i] = breakcost[atm];
00699 }
00700
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
00723
00724
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
00743
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
00756 lwInfo->getWalksatClausesWhenFlipped(atm, newClauses, newClauseWeights);
00757
00758 bool initial = false;
00759 addNewClauses(initial);
00760 lwInfo->setActive(atm);
00761
00762
00763
00764 }
00765 else
00766 {
00767
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
00790 lwInfo->setInBlock(false);
00791 lwInfo->setOtherAtom(-1);
00792 }
00793 }
00794
00795
00796 }
00797
00798
00799 void LazyWalksat::addNewClauses(bool initial)
00800 {
00801
00802 allClauses.append(newClauses);
00803 allClauseWeights.append(newClauseWeights);
00804 newClauses.clear();
00805 newClauseWeights.clear();
00806
00807 int i;
00808 int j;
00809
00810 int lit;
00811 int litindex;
00812
00813
00814 int oldnumclause = numclause;
00815 int oldnumatom = numatom;
00816
00817 numatom = lwInfo->getVarCount();
00818 numclause = allClauses.size();
00819
00820
00821
00822
00823
00824
00825 if(clausemem < numclause )
00826 {
00827
00828 if (2*numclause > clauseLimit)
00829 allocateClauseMemory(clauseLimit);
00830 else
00831 allocateClauseMemory(2*numclause);
00832 }
00833
00834
00835 if(atommem < numatom)
00836 {
00837 allocateAtomMemory(2*numatom);
00838 }
00839
00840
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
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;
00894 clauseFreeStore--;
00895 numliterals++;
00896 litindex = 2*abs(lit) - LWUtil::mySign(lit);
00897 newnumoccurence[litindex]++;
00898 }
00899 }
00900 }
00901
00902
00903
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
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
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
00950 }
00951
00952
00953 void LazyWalksat::trimClauses()
00954 {
00955 Array<int> idxOfDeactivated;
00956 if (!haveDeactivated)
00957 {
00958 haveDeactivated = true;
00959
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
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
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
01036 bool initial = true;
01037 addNewClauses(initial);
01038 }
01039
01040
01041 void LazyWalksat::initializeBreakCost(int startclause)
01042 {
01043
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
01051 if((clause[i][j] > 0) == atom[abs(clause[i][j])])
01052 {
01053 numtruelit[i]++;
01054 thetruelit = clause[i][j];
01055 }
01056 }
01057
01058
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
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
01077 else if (numtruelit[i] == 1 && cost[i] >= 0)
01078 {
01079 breakcost[abs(thetruelit)] += cost[i];
01080 }
01081
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
01091 }
01092
01093
01094 void LazyWalksat::allocateClauseMemory(int allocCount)
01095 {
01096
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
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;
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
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
01245 if (cost[cli] < 0)
01246 {
01247
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
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
01269 else
01270 {
01271 if (--numtruelit[cli] == 0)
01272 {
01273 falseclause[numfalse] = cli;
01274 wherefalse[cli] = numfalse;
01275 numfalse++;
01276 costofnumfalse += cost[cli];
01277
01278 breakcost[toflip] -= cost[cli];
01279 if (cost[cli] == highestcost) { eqhighest = true; numhighest++; }
01280 }
01281 else if (numtruelit[cli] == 1)
01282 {
01283
01284 sz = size[cli];
01285 litptr = clause[cli];
01286 for (j = 0; j < sz; j++)
01287 {
01288
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
01309 if (cost[cli] < 0)
01310 {
01311
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
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
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
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
01348
01349 sz = size[cli];
01350 litptr = clause[cli];
01351 for (j = 0; j < sz; j++)
01352 {
01353
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
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
01410 if (cost[i] < 0)
01411 bad = false;
01412
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
01424 if (cost[i] < 0)
01425 bad = true;
01426
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
01456 if (cost[i] < 0)
01457 bad = false;
01458
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
01469 if (cost[i] < 0)
01470 bad = true;
01471
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
01492 if (cost[i] < 0)
01493 bad = false;
01494
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
01505 if (cost[i] < 0)
01506 bad = true;
01507
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
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
01592
01593 return(falseclause[i-1]);
01594 }
01595
01596
01597 int LazyWalksat::pickrandom(int *numbreak, int clausesize, int tofix)
01598
01599 {
01600 return(random()%clausesize);
01601 }
01602
01603 int LazyWalksat::pickproductsum(int *numbreak, int clausesize, int tofix)
01604
01605
01606 {
01607 int i;
01608 int weight[MAXLENGTH];
01609 int tochange;
01610 int totalproduct = 1;
01611 int totalsum = 0;
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
01632 {
01633 int i;
01634 int weight[MAXLENGTH];
01635 int tochange;
01636 int totalproduct = 1;
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
01651 {
01652 int i;
01653 int weight[MAXLENGTH];
01654 int tochange;
01655 int totalsum = 0;
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;
01671 int best[MAXLENGTH];
01672 int numbest;
01673 int bestvalue;
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);
01692
01693
01694 numbest = 0;
01695 for (i = 0; i < clausesize; i++)
01696 {
01697 if (numbreak[i] < highestcost)
01698 {
01699 best[numbest++] = i;
01700 }
01701 }
01702
01703 if (numbest == 0) { return(random()%clausesize); }
01704 }
01705
01706 if (numbest == 1) return best[0];
01707
01708
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;
01718 int best[MAXLENGTH];
01719 int numbest;
01720 int bestvalue;
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;
01760 int weight[MAXLENGTH];
01761 int tochange;
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];
01772 }
01773
01774 return(pickweight(weight,clausesize));
01775 }
01776
01777 int LazyWalksat::pickzero(int *numbreak,int clausesize)
01778 {
01779 int i;
01780 int numzero = 0;
01781 int select;
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;
01802 int total = 0;
01803 int select;
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
01817 bool LazyWalksat::simAnnealing()
01818 {
01819
01820 if (lwInfo->getNumDBAtoms() == 0)
01821 {
01822 numnullflip++;
01823 return true;
01824 }
01825
01826 int toflip = -1;
01827
01828 int change;
01829
01830 if (numfalse == 0 || (random() % 100 < saRatio && !latesa))
01831 {
01832 bool initial = false;
01833
01834 if (lwInfo->activateRandomAtom(newClauses, newClauseWeights, toflip))
01835 addNewClauses(initial);
01836
01837
01838 if ((haveDeactivated && lwInfo->isDeactivated(toflip)) ||
01839 (lwInfo->inBlockWithEvidence(toflip)))
01840 {
01841 numnullflip++;
01842 return true;
01843 }
01844
01845
01846
01847
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
01861
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
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
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
01912
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
01925
01926 }
01927
01928
01929
01930
01931
01932 void LazyWalksat::initFixedAtoms(Array<Array<int> *> &clauses,
01933 Array<int> &clauseWeights)
01934 {
01935
01936
01937
01938
01939
01940
01941 bool done = false;
01942 while (!done)
01943 {
01944 done = true;
01945
01946
01947 for (int i = 0; i < clauses.size(); i++)
01948 {
01949 Array<int>* clause = clauses[i];
01950
01951
01952 if (clause->size() < 1)
01953 {
01954
01955
01956 delete clauses.removeItemFastDisorder(i);
01957 clauseWeights.removeItemFastDisorder(i);
01958 i--;
01959 continue;
01960 }
01961
01962
01963 if (clauseWeights[i] < 0)
01964 {
01965 for (int j = 0; j < clause->size(); j++)
01966 {
01967 int atm = (*clause)[j];
01968
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
01977 if (atm < 0)
01978 {
01979 lwInfo->setVarVal(abs(atm), true);
01980 }
01981
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
01996 if (clause->size() == 1)
01997 {
01998 int atm = (*clause)[0];
01999
02000
02001 if (!fixedAtoms_[abs(atm)])
02002 {
02003 lwInfo->setInactive(abs(atm));
02004 lwInfo->setEvidence(abs(atm), true);
02005 lwInfo->decrementNumDBAtoms();
02006 done = false;
02007
02008 fixedAtoms_[abs(atm)] = true;
02009
02010
02011 if ((clauseWeights[i] > 0 && atm > 0) ||
02012 (clauseWeights[i] < 0 && atm < 0))
02013 {
02014 lwInfo->setVarVal(abs(atm), true);
02015 }
02016
02017
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
02029
02030 continue;
02031 }
02032
02033
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
02042 if (Database::sameTruthValueAndSense(tv, sense))
02043 {
02044
02045
02046 delete clauses.removeItemFastDisorder(i);
02047 clauseWeights.removeItemFastDisorder(i);
02048 i--;
02049 break;
02050 }
02051
02052 else
02053 {
02054 clause->removeItemFastDisorder(j);
02055 j--;
02056 done = false;
02057 }
02058 }
02059
02060
02061
02062 }
02063 }
02064 }
02065
02066
02067
02068
02069
02070
02071
02072 }