#include <hmaxwalksat.h>
Inheritance diagram for HMaxWalkSat:
Public Member Functions | |
HMaxWalkSat (HVariableState *state, int seed, const bool &trackClauseTrueCnts, MaxWalksatParams *params) | |
Constructor: user-set parameters are set. | |
~HMaxWalkSat () | |
Destructor (destructors from superclasses are called). | |
void | SetMaxSeconds (double maxSeconds) |
void | SetNoisePra (int numerator, int denominator) |
void | SetSAInterval (int saInterval) |
void | init () |
Initializes the HMaxWalkSat algorithm. | |
double | getTargetCost () |
void | setSATempDownRatio (double saTempDownRatio) |
void | infer () |
Performs the given number of HMaxWalkSat inference tries. | |
const int | getHeuristic () |
void | setHeuristic (const int &heuristic) |
virtual const Array< double > * | getClauseTrueCnts () |
virtual const Array< double > * | getClauseTrueCntsCont () |
double | collapseDepthConstraint (double th) |
Protected Member Functions | |
void | flipAtom (int toFlip) |
Flips the truth value of an atom and marks this iteration as the last time it was flipped. | |
int | pickRandom () |
Pick a random atom in a random unsatisfied pos. | |
int | pickBest () |
Pick the best atom (clauses made satisfied - clauses made unsatisfied) in a random unsatisfied clause. | |
int | pickHMCS () |
Pick the atom idx according to hybrid WalkSAT strategy. | |
void | checkAr (const Array< int > &ar) |
int | pickHMWS () |
int | pickSA () |
int | pickSS () |
Pick an atom according to the SampleSat heuristic. | |
long double | calculateImprovementDisHMCS (const int &atomIdx) |
Calculates the improvement (makecost - breakcost) by flipping an atom. | |
long double | calculateImprovementDisHMWS (int atomIdx) |
void | reconstructLowState () |
Reconstructs the state with the lowest cost by flipping atoms back to their value in this state. | |
Classes | |
struct | FlipDisVarIdxCont |
This code is based on the HMaxWalkSat package of Kautz et al. and SampleSat by Wei et al.
Walksat is achieved by using unit weights (1 and -1) in the clauses in the state and setting the target cost to 0.
SampleSat is achieved by using unit weights (1 and -1) in the clauses in the state and setting the target cost to 0 and the heuristic to SS.
Definition at line 97 of file hmaxwalksat.h.
void HMaxWalkSat::init | ( | ) | [inline, virtual] |
Initializes the HMaxWalkSat algorithm.
A random assignment is given to the atoms and the state is initialized.
Implements Inference.
Definition at line 175 of file hmaxwalksat.h.
References SAT::changed_, HVariableState::getNumAtoms(), Array< Type >::growToSize(), Inference::hstate_, HVariableState::initRandom(), Array< Type >::shrinkToSize(), and Array< Type >::size().
Referenced by infer(), and HMCSAT::init().
00176 { 00177 if (heuristic_ == TABU || heuristic_ == SS || heuristic_ == HMWS) 00178 { 00179 int numAtoms = hstate_->getNumAtoms(); 00180 if (changed_.size() != numAtoms + 1) 00181 { 00182 if (int(changed_.size()) < numAtoms + 1) { 00183 changed_.growToSize(numAtoms + 1); 00184 } else { 00185 changed_.shrinkToSize(numAtoms + 1); 00186 } 00187 } 00188 for(int i = 1; i <= numAtoms; ++i) 00189 changed_[i] = -(tabuLength_ + 1); 00190 } 00191 00192 // Random initialize the variables 00193 hstate_->initRandom(); 00194 //reinitialize the SATemp here 00195 saTemp_ = saTempInit_; 00196 }
void HMaxWalkSat::flipAtom | ( | int | toFlip | ) | [inline, protected] |
Flips the truth value of an atom and marks this iteration as the last time it was flipped.
toFlip | Index of atom to flip. |
Definition at line 503 of file hmaxwalksat.h.
References SAT::changed_, HVariableState::flipAtom(), HVariableState::getNumAtoms(), Array< Type >::growToSize(), Inference::hstate_, and SAT::numFlips_.
Referenced by infer(), and pickHMCS().
00504 { 00505 //if (hmwsdebug) cout << "Entering HMaxWalkSat::flipAtom" << endl; 00506 if (toFlip == NOVALUE) 00507 return; 00508 00509 // Flip the atom in the state 00510 hstate_->flipAtom(toFlip, -1); 00511 // Mark this flip as last time atom was changed if tabu is used 00512 if (heuristic_ == TABU || heuristic_ == SS || heuristic_ == HMWS) 00513 { 00514 changed_[toFlip] = numFlips_; 00515 changed_.growToSize(hstate_->getNumAtoms() + 1, -(tabuLength_ + 1)); 00516 } 00517 00518 if (lazyLowState_) 00519 { 00520 // Mark this variable as flipped since last low state. If already 00521 // present, then it has been flipped back to its value in the low 00522 // state and we can remove it. 00523 if (varsFlippedSinceLowState_.find(toFlip) != 00524 varsFlippedSinceLowState_.end()) 00525 { 00526 varsFlippedSinceLowState_.erase(toFlip); 00527 } 00528 else 00529 { 00530 varsFlippedSinceLowState_.insert(toFlip); 00531 } 00532 } 00533 if (hmwsdebug) cout << "Leaving HMaxWalkSat::flipAtom" << endl; 00534 }
int HMaxWalkSat::pickRandom | ( | ) | [inline, protected] |
Pick a random atom in a random unsatisfied pos.
clause or a random true literal in a random satsified neg. clause to flip.
Definition at line 542 of file hmaxwalksat.h.
Referenced by HMaxWalkSat().
int HMaxWalkSat::pickBest | ( | ) | [inline, protected] |
Pick the best atom (clauses made satisfied - clauses made unsatisfied) in a random unsatisfied clause.
Definition at line 553 of file hmaxwalksat.h.
Referenced by HMaxWalkSat().
int HMaxWalkSat::pickHMCS | ( | ) | [inline, protected] |
Pick the atom idx according to hybrid WalkSAT strategy.
Definition at line 563 of file hmaxwalksat.h.
References Array< Type >::append(), HVariableState::atom_, calculateImprovementDisHMCS(), SAT::changed_, HVariableState::clauseCost_, Array< Type >::clear(), flipAtom(), HVariableState::getAtomInClause(), HVariableState::getClauseCost(), HVariableState::getClauseSize(), HVariableState::GetImprovementBySolvingHybridConstraintToContVar(), HVariableState::getRandomFalseClauseIndexHMCS(), HVariableState::getValueOfAtom(), Inference::hstate_, HVariableState::HybridClauseContPartValue(), HVariableState::HybridClauseValue(), HVariableState::hybridConjunctionDisjunction_, HVariableState::hybridConstraints_, HVariableState::hybridContClause_, HVariableState::hybridDisClause_, HVariableState::hybridWts_, HVariableState::isSatisfied(), SAT::numFlips_, HVariableState::printDisClause(), HVariableState::printHybridConstraint(), Array< Type >::size(), HVariableState::SolveConstraintAndRandomSample(), HVariableState::SolveHybridConstraintToContVarSample(), HVariableState::UpdateHybridClauseInfoByContAtom(), and HVariableState::UpdateHybridClauseInfoByDisAtom().
Referenced by HMaxWalkSat(), and pickSS().
00564 { 00565 if (wjhmwsdebug) 00566 { 00567 cout << "HMCS" << endl; 00568 } 00569 00570 assert(!inBlock_); 00571 // Clause to fix picked at random 00572 // need to be changed to deal with hybrid case 00573 bool noisyPick = (numerator_ > 0 && random() % denominator_ < numerator_); 00574 // Pick a clause. 00575 // For H-MCSAT, the picked clause is either a false discrete clause, or a hybrid one not satisfying the inequality constraint. 00576 // For HMWS, the picked clause is either a false discrete clause or a hybrid one. 00577 int toFix = hstate_->getRandomFalseClauseIndexHMCS(); // HMCS version. 00578 if (toFix == NOVALUE) // No false clause. 00579 { 00580 return NOVALUE; 00581 } 00582 else if (toFix > 0) //discrete clause, clause idx = toFix - 1; 00583 { 00584 toFix --; 00585 if (wjhmwsdebug) 00586 { 00587 cout << "Pick false dis clause: " << toFix << ", "; hstate_->printDisClause(toFix, cout); cout << "Cost: " << hstate_->clauseCost_[toFix] << endl; 00588 } 00589 long double improvement; 00590 int clauseSize = hstate_->getClauseSize(toFix); 00591 long double cost = hstate_->getClauseCost(toFix); 00592 // Holds the best atoms so far 00593 Array<int> best; 00594 // How many are tied for best 00595 register int numbest = 0; 00596 // Best value so far 00597 long double bestvalue = -LDBL_MAX; 00598 // With prob. do a noisy pick, prob = denominator / numerator. 00599 // if random move, exclude illegitimate ones and place others in a lottery 00600 if (noisyPick) 00601 { 00602 for (int i = 0; i < clauseSize; ++i) 00603 { 00604 register int lit = hstate_->getAtomInClause(i, toFix); 00605 // Neg. clause: Only look at true literals 00606 if (cost < 0 && !hstate_->isTrueLiteral(lit)) continue; 00607 best.append(abs(lit)); 00608 numbest++; 00609 } 00610 } // Noisy pick ends. 00611 else // Greedy: pick the best value 00612 { 00613 for (int i = 0; i < clauseSize; ++i) 00614 { 00615 register int lit = hstate_->getAtomInClause(i, toFix); 00616 // Neg. clause: Only look at true literals 00617 if (cost < 0 && !hstate_->isTrueLiteral(lit)) continue; 00618 // var is the index of the atom 00619 register int var = abs(lit); 00620 improvement = calculateImprovementDisHMCS(var); 00621 if (mwsdebug) { 00622 cout << "Improvement of var " << var << " is: " << improvement << endl; 00623 } 00624 00625 // TABU: If pos. improvement, then always add it to best 00626 if (improvement > 0 && improvement >= bestvalue) 00627 { // Tied or better than previous best 00628 if (improvement > bestvalue) 00629 { 00630 numbest = 0; 00631 best.clear(); 00632 } 00633 bestvalue = improvement; 00634 best.append(var); 00635 numbest++; 00636 } else if (improvement > -LDBL_MAX && tabuLength_ < numFlips_ - changed_[var]) { 00637 if (improvement >= bestvalue) 00638 { // Tied or better than previous best 00639 if (improvement > bestvalue) 00640 { 00641 numbest = 0; 00642 best.clear(); 00643 } 00644 bestvalue = improvement; 00645 best.append(var); 00646 numbest++; 00647 } 00648 } 00649 } 00650 } 00651 00652 if (numbest == 0) 00653 { 00654 if (wjhmwsdebug) cout << "Leaving MaxWalkSat::pickHMCS (NOVALUE)" << endl; 00655 return NOVALUE; 00656 } 00657 int toFlip = NOVALUE; 00658 // Exactly one best atom 00659 if (numbest == 1) { 00660 toFlip = best[0]; 00661 } else { 00662 // Choose one of the best at random 00663 toFlip = best[random()% best.size()]; 00664 } 00665 00666 if (wjhmwsdebug) 00667 { 00668 cout << "Improvement:" << bestvalue << endl; 00669 } 00670 return toFlip; 00671 } // Discrete clause 00672 else // Hybrid clause, clause idx = - (toFix + 1); toFix < 0 00673 { 00674 toFix++; 00675 int contClauseIdx = -toFix; 00676 // If the weight of the hybrid constraint is 0, then we skip the current pick. 00677 if (hstate_->hybridWts_[contClauseIdx] == 0) return NOVALUE; 00678 00679 if (wjhmwsdebug) { 00680 cout << "Pick false hybrid clause: " << contClauseIdx << ", constraint:"; hstate_->printHybridConstraint(contClauseIdx, cout); 00681 } 00682 int contVarNum = hstate_->hybridContClause_[contClauseIdx].size(); 00683 int disVarNum = hstate_->hybridDisClause_[contClauseIdx].size(); 00684 int totalVarNum = contVarNum + disVarNum; 00685 if (noisyPick) // Random pick and then flip, p = numerator_/denominator_; 00686 { 00687 set<int> pickedContVars; 00688 int inIdx = random() % totalVarNum; 00689 if (inIdx < contVarNum) // Continuous variable 00690 { 00691 int contAtomIdx = hstate_->hybridContClause_[contClauseIdx][inIdx]; 00692 // Solve the constraint in regarding with the chosen continuous variable. 00693 // Then compute the improvement in term of #false clause reduction. 00694 pickedContValue_ = hstate_->SolveHybridConstraintToContVarSample(contClauseIdx, inIdx); 00695 if (pickedContValue_ == FLIPDIS) { 00696 // Generate a random solution to the discrete part of the hybrid clause, so that making it true. 00697 Array<bool> solution; 00698 GetClauseRandomSolution(hstate_->hybridDisClause_[contClauseIdx].size(), true, hstate_->hybridConjunctionDisjunction_[contClauseIdx], &solution); 00699 // Update each discrete variable. 00700 for (int i = 0; i < solution.size(); ++i) { 00701 int atomIdx = hstate_->hybridDisClause_[contClauseIdx][i]; 00702 if (solution[i] != hstate_->getValueOfAtom(atomIdx)) { 00703 flipAtom(atomIdx); 00704 bool atomValue = hstate_->getValueOfAtom(atomIdx); 00705 hstate_->UpdateHybridClauseInfoByDisAtom(atomIdx, atomValue); 00706 } 00707 } 00708 // Then check if the continuous part's value satisfies the constraint or not. 00709 double cont_part_value = hstate_->HybridClauseContPartValue(contClauseIdx); 00710 if (cont_part_value < hstate_->hybridConstraints_[contClauseIdx].vThreshold_) { 00711 // If not, solve the continuous part for the given variable, set both solutions and update status. 00712 double cont_var_value = hstate_->SolveConstraintAndRandomSample(contClauseIdx, inIdx); 00713 if (cont_var_value == UNSOLVABLE) 00714 return NOVALUE; 00715 else { 00716 // Update by the continuous variable. 00717 hstate_->UpdateHybridClauseInfoByContAtom(contAtomIdx, cont_var_value); 00718 } 00719 } 00720 00721 // Return the status that no action needs to be performed. 00722 return NOVALUE; 00723 } // FLIP_DIS ends 00724 00725 return -contAtomIdx; 00726 } 00727 else // discrete variable 00728 { 00729 // Check if flipping this discrete variable could satisfy this constraint. 00730 // If so, return it, if not, do nothing. 00731 int atomIdx = abs(hstate_->hybridDisClause_[contClauseIdx][inIdx - contVarNum]); 00732 hstate_->atom_[atomIdx] = !hstate_->atom_[atomIdx]; 00733 double hybrid_clause_val = hstate_->HybridClauseValue(contClauseIdx); 00734 hstate_->atom_[atomIdx] = !hstate_->atom_[atomIdx]; 00735 if (hstate_->isSatisfied(hstate_->hybridConstraints_[contClauseIdx], hybrid_clause_val)) { 00736 return atomIdx; 00737 } else { 00738 return NOVALUE; 00739 } 00740 } 00741 } // Noisy pick 00742 else //greedy try to flip every variable and find the one get biggest improvement 00743 { 00744 long double bestvalue = -LDBL_MAX; 00745 Array<int> best; 00746 int numbest = 0; 00747 map<int, double> pickedContValues; 00748 for (int i = 0; i < contVarNum; ++i) { 00749 int contAtomIdx = hstate_->hybridContClause_[contClauseIdx][i]; 00750 // Solve the constraint in regarding with the chosen continuous variable. 00751 // Then compute the improvement in term of #false clause reduction. 00752 double cont_var_val = 0; 00753 double improvement = 00754 hstate_->GetImprovementBySolvingHybridConstraintToContVar(contClauseIdx, i, cont_var_val); 00755 // Tied or better than previous best 00756 if (improvement != CANNOTSATCURRENT && improvement >= bestvalue) { 00757 if (improvement > bestvalue) { 00758 numbest = 0; 00759 best.clear(); 00760 } 00761 bestvalue = improvement; 00762 best.append(-contAtomIdx); 00763 numbest++; 00764 pickedContValues[-contAtomIdx] = cont_var_val; 00765 } 00766 } 00767 00768 for (int i = 0; i < disVarNum; ++i) { 00769 int disAtomIdx = hstate_->hybridDisClause_[contClauseIdx][i]; 00770 double improvement = calculateImprovementDisHMCS(disAtomIdx); 00771 00772 if (improvement >= bestvalue) 00773 { // Tied or better than previous best 00774 if (improvement > bestvalue) 00775 { 00776 numbest = 0; 00777 best.clear(); 00778 } 00779 bestvalue = improvement; 00780 best.append(disAtomIdx); 00781 numbest++; 00782 } 00783 } 00784 00785 int atomIdx = NOVALUE; 00786 // Exactly one best atom 00787 if (numbest == 1) 00788 atomIdx = best[0]; 00789 else 00790 // Choose one of the best at random 00791 atomIdx = best[random()%numbest]; 00792 00793 if (atomIdx < 0) // Picked variable is a continuous variable. 00794 { 00795 pickedContValue_ = pickedContValues[atomIdx]; 00796 } 00797 return atomIdx; 00798 } // Greedy 00799 } // Hybrid clause. 00800 return NOVALUE; 00801 }
int HMaxWalkSat::pickSS | ( | ) | [inline, protected] |
Pick an atom according to the SampleSat heuristic.
This means sometimes sim. annealing, sometimes HMaxWalkSat.
Definition at line 1116 of file hmaxwalksat.h.
References calculateImprovementDisHMCS(), HVariableState::getCostOfTotalFalseConstraints(), HVariableState::GetImprovementByMovingContVar(), HVariableState::getIndexOfRandomAtom(), Inference::hstate_, pickHMCS(), HVariableState::printContAtom(), HVariableState::printDisAtom(), and SAT::targetCost_.
Referenced by HMaxWalkSat().
01117 { 01118 long double costOfFalseClauses = hstate_->getCostOfTotalFalseConstraints(); 01119 // If we have already reached a solution or if in an SA step, 01120 // then perform SA 01121 if (costOfFalseClauses <= targetCost_ + SMALLVALUE || (random() % 100 < saRatio_ && !lateSa_)) 01122 { 01123 if (wjhmwsdebug) 01124 { 01125 cout << "SASTEP" << endl; 01126 } 01127 // Choose a random atom to flip 01128 int toFlip = hstate_->getIndexOfRandomAtom(); //change to hybrid, pos, discrete, neg, continuous 01129 if (toFlip > 0) // Discrete atom. 01130 { 01131 if (wjhmwsdebug) 01132 { 01133 cout << "Choose to flip dis atom " << toFlip << ":";hstate_->printDisAtom(toFlip, cout); 01134 } 01135 long double improvement = calculateImprovementDisHMCS(toFlip); 01136 01137 if (wjhmwsdebug) 01138 { 01139 cout << "By flipping, improvement is " << improvement << endl; 01140 } 01141 01142 // If pos. or no improvement, then the atom will be flipped 01143 // Or neg. improvement: According to temp. flip atom anyway 01144 if ((improvement >= 0) || (random() <= exp(improvement/(saTemp_/100.0)) * RAND_MAX)) 01145 { 01146 return toFlip; 01147 } 01148 else 01149 { 01150 return NOVALUE; 01151 } 01152 } 01153 else // Continuous variable. 01154 { 01155 //generate the new value for the continuous variable according to the proposal distribution 01156 int contAtomIdx = -toFlip; 01157 double vContAtomFlipped; 01158 long double improvement = hstate_->GetImprovementByMovingContVar(contAtomIdx, vContAtomFlipped); 01159 01160 if (wjhmwsdebug) 01161 { 01162 cout << "Choose to move cont atom " << contAtomIdx << ":";hstate_->printContAtom(contAtomIdx, cout); 01163 cout << " To " << vContAtomFlipped << ", improvement is " << improvement << endl; 01164 } 01165 01166 if ((improvement >= 0) || 01167 (random() <= exp(improvement/(saTemp_/100.0)) * RAND_MAX)) 01168 { 01169 pickedContValue_ = vContAtomFlipped; //the value picked. 01170 return toFlip; //neg, indicate cont variable. 01171 } 01172 else 01173 { 01174 return NOVALUE; 01175 } 01176 } 01177 } 01178 // Not in a solution or SA step: perform Hybrid WalkSAT step 01179 else 01180 { 01181 return pickHMCS(); // TODO: juewang 01182 } 01183 }
long double HMaxWalkSat::calculateImprovementDisHMCS | ( | const int & | atomIdx | ) | [inline, protected] |
Calculates the improvement (makecost - breakcost) by flipping an atom.
If the atom is in a block, then its index is saved in candidateBlockedVars and the index of another atom chosen to be flipped in the block is appended to othersToFlip. If the atom is in a block with evidence, then its index is appended to canNotFlip.
atomIdx | Index of atom for which the improvement is calculated. | |
canNotFlip | Holds indices of atoms which can not be flipped due to evidence in a block. | |
candidateBlockedVars | If dealing with an atom in a block, then its index is appended here. | |
othersToFlip | If dealing with an atom in a block, then the index of the other atom chosen to be flipped is appended here. |
Definition at line 1200 of file hmaxwalksat.h.
References HVariableState::getImprovementByFlippingDisHMCS(), and Inference::hstate_.
Referenced by pickHMCS(), and pickSS().
01201 { 01202 return hstate_->getImprovementByFlippingDisHMCS(atomIdx); 01203 }