00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #include "samplesat.h"
00075 #include "timer.h"
00076
00077 char* heuristic_names[] = { "random", "best", "tabu", "sa"};
00078
00079
00080
00081
00082 SampleSat::SampleSat(const SampleSatParams & params, int numGndPreds, int maxClause,
00083 int maxLen, int maxLitOccurence, int* fixedAtoms, int** clauses,
00084 const Array<Array<int> >* const & blocks,
00085 const Array<bool >* const & blockEvidence)
00086 {
00087 cout<<"Init Samplesat ..."<<endl;
00088
00089
00090 saRatio = params.saRatio;
00091 temperature = params.temperature;
00092 latesa = params.latesa;
00093 numsol = params.numsol;
00094 numerator = params.ws_noise;
00095 numrun = params.ws_restart;
00096 cutoff = base_cutoff = params.ws_cutoff;
00097
00098
00099 numatom = MAXATOM = numGndPreds;
00100 MAXCLAUSE = maxClause;
00101 MAXLENGTH = maxLen;
00102
00103
00104 numoccurence = new int[2*MAXATOM+1];
00105 atom = new int[2*MAXATOM+1];
00106 lowatom = new int[2*MAXATOM+1];
00107 solution = new int[2*MAXATOM+1];
00108 changed = new int[2*MAXATOM+1];
00109 breakcount = new int[2*MAXATOM+1];
00110 makecount = new int[2*MAXATOM+1];
00111
00112
00113
00114 fixedatom = fixedAtoms;
00115 isSat = new bool[MAXCLAUSE];
00116
00117 blocks_ = new Array<Array<int> >(*blocks);
00118 blockEvidence_ = new Array<bool>(*blockEvidence);
00119
00120
00121 inBlock = false;
00122 flipInBlock = NOVALUE;
00123 clause = clauses;
00124
00125 size = new int[MAXCLAUSE];
00126 wfalse = new int[MAXCLAUSE];
00127 lowfalse = new int[MAXCLAUSE];
00128 wherefalse = new int[MAXCLAUSE];
00129 numtruelit = new int[MAXCLAUSE];
00130
00131
00132 watch1 = new int[MAXCLAUSE];
00133 watch2 = new int[MAXCLAUSE];
00134
00135 occurence = new int*[2*MAXATOM+1];
00136 for (int i = 0; i <= 2*MAXATOM; i++)
00137 {
00138 occurence[i] = new int[maxLitOccurence];
00139 }
00140
00141 int idx = 0;
00142 pickcode[idx++] = &SampleSat::pickrandom;
00143 pickcode[idx++] = &SampleSat::pickbest;
00144 pickcode[idx++] = &SampleSat::picktabu;
00145 pickcode[idx++] = &SampleSat::picksa;
00146
00147
00148 denominator = 100;
00149 heuristic = SA;
00150 tabu_length = 5;
00151 wp_numerator = NOVALUE;
00152 wp_denominator = 100;
00153 superlinear = true;
00154
00155 makeflag = true;
00156
00157
00158 tail = 3;
00159
00160
00161 printonlysol = false;
00162 printsolcnf = false;
00163 printfalse = false;
00164 printlow = false;
00165 printhist = false;
00166 printtrace = 0;
00167
00168 trace_assign = false;
00169
00170 outfile[0] = 0;
00171
00172
00173 initfile[0] = 0;
00174 initoptions = false;
00175 }
00176
00177 SampleSat::~SampleSat()
00178 {
00179 for (int i = 0; i <= 2*MAXATOM; i++)
00180 {
00181 delete [] occurence[i];
00182 }
00183 delete [] occurence;
00184 delete [] numoccurence;
00185 delete [] atom;
00186 delete [] lowatom;
00187 delete [] solution;
00188 delete [] changed;
00189 delete [] breakcount;
00190 delete [] makecount;
00191
00192 delete [] size;
00193 delete [] wfalse;
00194 delete [] lowfalse;
00195 delete [] wherefalse;
00196 delete [] numtruelit;
00197
00198 delete [] watch1;
00199 delete [] watch2;
00200
00201 for (int i = 0; i < blocks_->size(); i++)
00202 (*blocks_)[i].clearAndCompress();
00203 delete blocks_;
00204
00205 delete blockEvidence_;
00206 }
00207
00208
00209 bool SampleSat::sample(bool*& assignments, int numClauses,
00210 const Array<Array<int> >* const & blocks,
00211 const Array<bool>* const & blockEvidence)
00212 {
00213
00214 gettimeofday(&tv,&tzp);
00215 seed = (unsigned int)((( tv.tv_sec & 0177 ) * 1000000) + tv.tv_usec);
00216 srandom(seed);
00217
00218 for (int i = 0; i < blocks_->size(); i++)
00219 (*blocks_)[i].clearAndCompress();
00220 delete blocks_;
00221 delete blockEvidence_;
00222
00223 blocks_ = new Array<Array<int> >(*blocks);
00224 blockEvidence_ = new Array<bool>(*blockEvidence);
00225
00226
00227 numclause = numClauses;
00228
00229
00230 if (numclause == 0)
00231 {
00232
00233 for (int i = 0; i < blocks_->size(); i++)
00234 {
00235 Array<int> block = (*blocks_)[i];
00236
00237
00238 if (fixedAtomInBlock(i))
00239 continue;
00240
00241
00242 if ((*blockEvidence_)[i])
00243 {
00244
00245 setOthersInBlockToFalse(assignments, -1, i);
00246 continue;
00247 }
00248
00249 int chosen = random() % block.size();
00250 assignments[block[chosen]] = true;
00251 setOthersInBlockToFalse(assignments, chosen, i);
00252 }
00253
00254
00255 for (int i = 1; i <= MAXATOM; i++)
00256 {
00257 if (fixedatom[i] >= 0) assignments[i-1] = (fixedatom[i] == 1);
00258 else if (getBlock(i-1) >= 0) continue;
00259 else assignments[i-1] = (random() < RAND_MAX/2);
00260 }
00261 return true;
00262 }
00263
00264 initVars();
00265
00266 Timer timer;
00267 double begSec = timer.time();
00268
00269 if (!initprob())
00270 {
00271 return false;
00272 }
00273
00274
00275
00276
00277
00278
00279 if (numclause == 0)
00280 {
00281
00282 for (int i = 0; i < blocks_->size(); i++)
00283 {
00284 Array<int> block = (*blocks_)[i];
00285
00286
00287 if ((*blockEvidence_)[i])
00288 {
00289 for (int j = 0; j < block.size(); j++)
00290 {
00291 int newIdx = block[j];
00292 int oldIdx = newToOldMapping_[newIdx];
00293 assignments[oldIdx - 1] = false;
00294 }
00295 continue;
00296 }
00297
00298 int chosen = random() % block.size();
00299 int newIdx = block[chosen];
00300 int oldIdx = newToOldMapping_[newIdx];
00301 assignments[oldIdx - 1] = true;
00302 for (int j = 0; j < block.size(); j++)
00303 {
00304 if (j == chosen) continue;
00305 int newOtherIdx = block[j];
00306 int oldOtherIdx = newToOldMapping_[newOtherIdx];
00307 assignments[oldOtherIdx - 1] = false;
00308 }
00309 }
00310
00311
00312 for (int i = 1; i <= MAXATOM; i++)
00313 {
00314 if (fixedatom[i] >= 0) assignments[i-1] = (fixedatom[i] == 1);
00315 else if (getBlock(-(fixedatom[i] + 1)) >= 0) continue;
00316 else assignments[i-1] = (random() < RAND_MAX/2);
00317 }
00318
00319 return true;
00320 }
00321
00322 initRandom();
00323
00324 begSec = timer.time();
00325
00326 while (numsuccesstry < numsol && numtry < numrun*numsol)
00327 {
00328 numtry++;
00329
00330 numflip = 0;
00331 if (superlinear) cutoff = base_cutoff * super(numtry);
00332
00333 while(numflip < cutoff && numsuccesstry < numsol)
00334 {
00335 print_statistics_start_flip();
00336 numflip++;
00337 flipatom((this->*(pickcode[heuristic]))());
00338
00339 if (inBlock)
00340 {
00341 flipatom(flipInBlock);
00342 }
00343
00344 inBlock = false;
00345 flipInBlock = NOVALUE;
00346
00347
00348 if (numfalse==0) update_and_print_statistics_end_try();
00349 }
00350
00351
00352
00353 if (numsuccesstry <= 0) initRandom();
00354
00355
00356 }
00357
00358
00359
00360
00361 if (numsuccesstry > 0)
00362 {
00363 for (int i = 1; i <= MAXATOM; i++)
00364 {
00365 if (fixedatom[i] >= 0) assignments[i-1] = (fixedatom[i] == 1);
00366 else assignments[i-1] = (solution[-fixedatom[i]] == 1);
00367 }
00368 return true;
00369 }
00370 else return false;
00371 }
00372
00373
00374 bool SampleSat::initprob()
00375 {
00376
00377 int i;
00378 int lit;
00379
00380 if(numclause > MAXCLAUSE)
00381 {
00382 fprintf(stderr,"ERROR - too many clauses\n");
00383 exit(-1);
00384 }
00385
00386 bool done = false;
00387 int numfixedatom = 0, numsat = 0;
00388 for (i = 0; i < numclause; i++)
00389 {
00390 isSat[i] = false;
00391 }
00392
00393 while (!done)
00394 {
00395 done = true;
00396 for (i = 0; i < numclause; i++)
00397 {
00398 if (!isSat[i])
00399 {
00400 int nonUnitNum = 0;
00401 int nonUnitIdx = -1;
00402 int j = 0;
00403 while (clause[i][j] != 0)
00404 {
00405 int lit = clause[i][j];
00406 int var = (lit > 0)? lit : -lit;
00407 if (fixedatom[var] == -1)
00408 {
00409 nonUnitNum++;
00410 nonUnitIdx = j;
00411 }
00412 else
00413 if ((fixedatom[var] == 0 && lit < 0) ||
00414 (fixedatom[var] == 1 && lit > 0))
00415 {
00416 isSat[i] = true;
00417 numsat++;
00418 break;
00419 }
00420 j++;
00421 }
00422
00423
00424 if (!isSat[i] && nonUnitNum==1)
00425 {
00426 int lit = clause[i][nonUnitIdx];
00427 int var = (lit > 0)? lit : -lit;
00428 fixedatom[var] = (lit > 0)? 1 : 0;
00429 isSat[i] = true;
00430 done = false;
00431 numfixedatom++;
00432 numsat++;
00433 }
00434 }
00435 }
00436 }
00437
00438
00439
00440
00441 numliterals = 0;
00442 for(i = 0; i < 2*MAXATOM + 1; i++) numoccurence[i] = 0;
00443
00444 int nc = numclause;
00445 numatom = 0, numclause = 0;
00446 newToOldMapping_.clearAndCompress();
00447 for (i = 1; i <= MAXATOM; i++)
00448 {
00449
00450 if (fixedatom[i] < 0)
00451 {
00452 fixedatom[i] = -(++numatom);
00453 newToOldMapping_.append(i);
00454 }
00455 }
00456
00457
00458 for (i = 0; i < blocks_->size(); i++)
00459 {
00460 int fixedTrueAtoms = 0;
00461 Array<int>& block = (*blocks_)[i];
00462 for (int j = 0; j < block.size(); j++)
00463 {
00464 int num = fixedatom[block[j] + 1];
00465
00466 if (num == 1)
00467 {
00468 if (fixedTrueAtoms > 0)
00469 {
00470 cout << "Inconsistent fixed assignment! Two atoms in one block "
00471 << "are fixed to true through unit propagation." << endl;
00472 exit(-1);
00473 }
00474 if ((*blockEvidence_)[i])
00475 {
00476 cout << "Inconsistent fixed assignment! An atom in a block "
00477 << "is fixed to true which contradicts evidence." << endl;
00478 exit(-1);
00479 }
00480 fixedTrueAtoms++;
00481 block.removeItem(j--);
00482 }
00483
00484 else if (num == 0)
00485 {
00486 block.removeItem(j--);
00487 }
00488
00489 else
00490 {
00491 assert (num < 0);
00492 block[j] = -(num + 1);
00493 }
00494 }
00495
00496
00497
00498 if (fixedTrueAtoms > 0 || (*blockEvidence_)[i])
00499 {
00500 (*blockEvidence_)[i] = true;
00501 for (int j = 0; j < block.size(); j++)
00502 {
00503 atom[block[j] + 1] = false;
00504 }
00505 }
00506
00507 else if (block.size() == 0)
00508 {
00509 blocks_->removeItem(i);
00510 blockEvidence_->removeItem(i);
00511 i--;
00512 }
00513
00514 else
00515 {
00516 int chosen = random() % block.size();
00517 atom[block[chosen] + 1] = true;
00518 for (int j = 0; j < block.size(); j++)
00519 {
00520 if (j != chosen)
00521 {
00522 atom[block[j] + 1] = false;
00523 }
00524 }
00525 }
00526 }
00527
00528 for (i = 0; i < nc; i++)
00529 {
00530 if (!isSat[i])
00531 {
00532 int idx = 0;
00533 int k = 0;
00534 while (clause[i][k] != 0)
00535 {
00536 lit = clause[i][k++];
00537 int var = (lit > 0) ? lit: -lit;
00538
00539 assert(fixedatom[var] != (lit > 0));
00540
00541 if (fixedatom[var] >= 0) continue;
00542
00543 int newlit = (lit < 0) ? fixedatom[var] : -fixedatom[var];
00544 assert(numclause <= i && idx < k);
00545 clause[numclause][idx++] = newlit;
00546 numliterals++;
00547 occurence[newlit + MAXATOM][numoccurence[newlit + MAXATOM]++] = numclause;
00548 }
00549
00550 if (idx == 0)
00551 {
00552 cout << "Inconsistent fixed assignment!" << endl;
00553 return false;
00554 }
00555 size[numclause] = idx;
00556 numclause++;
00557 }
00558 }
00559 return true;
00560 }
00561
00562 void SampleSat::initRandom()
00563 {
00564 int i;
00565 int j;
00566 int thetruelit = -1;
00567 int truelit1;
00568 int truelit2;
00569
00570 for(i = 0; i < numclause; i++) numtruelit[i] = 0;
00571 numfalse = 0;
00572
00573 for(i = 1; i < numatom + 1; i++)
00574 {
00575 changed[i] = -BIG;
00576 breakcount[i] = 0;
00577 makecount[i] = 0;
00578 }
00579
00580
00581
00582
00583
00584
00585 for (int i = 0; i < blocks_->size(); i++)
00586 {
00587 Array<int> block = (*blocks_)[i];
00588
00589 if ((*blockEvidence_)[i])
00590 {
00591
00592 setOthersInBlockToFalse(-1, i);
00593 continue;
00594 }
00595
00596 int chosen = random() % block.size();
00597 atom[block[chosen] + 1] = true;
00598 setOthersInBlockToFalse(chosen, i);
00599 }
00600
00601
00602 for (int i = 1; i <= numatom; i++)
00603 {
00604 if (getBlock(i - 1) >= 0) continue;
00605 else atom[i] = (random() < RAND_MAX/2) ? 1 : 0;
00606 }
00607
00608
00609 for(i = 0; i < numclause; i++)
00610 {
00611 truelit1 = 0;
00612 truelit2 = 0;
00613 for(j = 0; j < size[i]; j++)
00614 {
00615 if((clause[i][j] > 0) == atom[abs(clause[i][j])])
00616 {
00617 numtruelit[i]++;
00618 thetruelit = clause[i][j];
00619
00620 if (!truelit1) truelit1 = clause[i][j];
00621 else if (truelit1 && !truelit2) truelit2 = clause[i][j];
00622 }
00623 }
00624
00625 if(numtruelit[i] == 0)
00626 {
00627 wherefalse[i] = numfalse;
00628 wfalse[numfalse] = i;
00629 numfalse++;
00630 for(j = 0; j < size[i]; j++) makecount[abs(clause[i][j])]++;
00631 }
00632 else
00633 if (numtruelit[i] == 1)
00634 {
00635 breakcount[abs(thetruelit)]++;
00636 watch1[i] = abs(thetruelit);
00637 }
00638 else
00639 {
00640 watch1[i] = abs(truelit1);
00641 watch2[i] = abs(truelit2);
00642 }
00643 }
00644
00645 if (hamming_flag)
00646 {
00647 hamming_distance = calc_hamming_dist(atom, hamming_target, numatom);
00648 fprintf(hamming_fp, "0 %i\n", hamming_distance);
00649 }
00650 }
00651
00652 void SampleSat::initVars()
00653 {
00654 status_flag = 0;
00655
00656 target = 0;
00657 numtry = 0;
00658 numsuccesstry = 0;
00659
00660
00661 hamming_target_file[0] = 0;
00662 hamming_data_file[0] = 0;
00663 hamming_flag = false;
00664 }
00665
00666 void SampleSat::print_parameters(int argc, char * argv[])
00667 {
00668 printf("cutoff = %li\n",cutoff);
00669 printf("tries = %i\n",numrun);
00670
00671 printf("heuristic = ");
00672 switch(heuristic)
00673 {
00674 case TABU:
00675 printf("tabu %d", tabu_length);
00676 break;
00677 default:
00678 printf("%s", heuristic_names[heuristic]);
00679 break;
00680 }
00681 if (numerator > 0)
00682 {
00683 printf(", noise %d / %d", numerator, denominator);
00684 }
00685 if (wp_numerator > 0)
00686 {
00687 printf(", wp %d / %d", wp_numerator, wp_denominator);
00688 }
00689 printf("\n");
00690 }
00691
00692 int SampleSat::picksa(void)
00693 {
00694 int change;
00695 int toflip;
00696
00697 if (numfalse == 0 || (random() % 100 < saRatio && !latesa))
00698 {
00699 toflip = random()%numatom + 1;
00700
00701 int blockIdx = getBlock(toflip - 1);
00702 if (blockIdx == -1)
00703 change = makecount[toflip] - breakcount[toflip];
00704 else
00705 {
00706
00707 if ((*blockEvidence_)[blockIdx] || (*blocks_)[blockIdx].size() == 1)
00708 return NOVALUE;
00709 change = calculateChange(toflip);
00710 }
00711
00712 if (change >= 0)
00713 return toflip;
00714 else if (random() <= exp(change/(temperature/100.0)) * RAND_MAX)
00715 return toflip;
00716 else
00717 {
00718
00719 inBlock = false;
00720 flipInBlock = NOVALUE;
00721 return NOVALUE;
00722 }
00723 }
00724 else
00725 {
00726
00727 return pickbest();
00728 }
00729 }
00730
00731 void SampleSat::update_and_print_statistics_end_try(void)
00732 {
00733 if(numfalse <= target)
00734 {
00735 status_flag = 0;
00736 save_solution();
00737 numsuccesstry++;
00738 }
00739 }
00740