heuristics.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006-2010, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 #ifndef CLASP_HEURISTICS_H_INCLUDED
00021 #define CLASP_HEURISTICS_H_INCLUDED
00022 
00023 #ifdef _MSC_VER
00024 #pragma once
00025 #endif
00026 
00033 #include <clasp/solver.h>
00034 #include <clasp/pod_vector.h>
00035 #include <clasp/util/indexed_priority_queue.h>
00036 #include <list>
00037 namespace Clasp { 
00038 
00039 // Some lookback heuristics to be used together with learning.
00040 
00042 uint32 momsScore(const Solver& s, Var v);
00043 
00044 struct HeuParams {
00045         HeuParams() : initScore(0), otherScore(0), resScore(0) {}
00046         HeuParams& other(uint32 x)   { otherScore = static_cast<uint8>(x);    return *this; }
00047         HeuParams& init(uint32 moms) { initScore  = static_cast<uint8>(moms); return *this; }
00048         HeuParams& score(uint32 x)   { resScore   = static_cast<uint8>(x);    return *this; }
00049         uint8 initScore; // currently {no, moms}
00050         uint8 otherScore;// currently {no, loop, all, heu}
00051         uint8 resScore;  // currently {heu, set}
00052 };
00053 
00055 
00066 class ClaspBerkmin : public DecisionHeuristic {
00067 public:
00072         explicit ClaspBerkmin(uint32 maxBerk = 0, const HeuParams& params = HeuParams(), bool berkHuang = false);
00073         void startInit(const Solver& s);
00074         void endInit(Solver& s);
00075         void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t);
00076         void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit);
00077         bool bump(const Solver& s, const WeightLitVec& lits, double adj);
00078         void undoUntil(const Solver&, LitVec::size_type);
00079         void updateVar(const Solver& s, Var v, uint32 n);
00080 protected:
00081         Literal doSelect(Solver& s);
00082 private:
00083         Literal selectLiteral(Solver& s, Var v, bool vsids) const;
00084         Literal selectRange(Solver& s, const Literal* first, const Literal* last);
00085         bool    initHuang() const { return order_.score[0].occ == 1; }
00086         void    initHuang(bool b) { order_.score[0].occ = b; }
00087         bool    hasActivities() const { return order_.score[0].act != 0; }
00088         void    hasActivities(bool b) { order_.score[0].act = b; }
00089         Var  getMostActiveFreeVar(const Solver& s);
00090         Var  getTopMoms(const Solver& s);
00091         bool hasTopUnsat(Solver& s);
00092         // Gathers heuristic information for one variable v.
00093         struct HScore {
00094                 HScore(uint32 d = 0) :  occ(0), act(0), dec(uint16(d)) {}
00095                 void incAct(uint32 gd, bool h, bool sign) {
00096                         occ += h * (1 - (2*sign));
00097                         decay(gd, h);
00098                         ++act;
00099                 }
00100                 void incOcc(bool sign) { occ += 1 - (2*sign); }
00101                 uint32 decay(uint32 gd, bool h) {
00102                         if (uint32 x = (gd-dec)) {
00103                                 // NOTE: shifts might overflow, i.e.
00104                                 // activity is actually shifted by x%32. 
00105                                 // We deliberately ignore this "logical inaccuracy"
00106                                 // and treat it as random noise ;)
00107                                 act >>= x;
00108                                 dec   = uint16(gd);
00109                                 occ  /= (1<<(x*h));
00110                         }
00111                         return act;
00112                 }
00113                 int32  occ;
00114                 uint16 act;
00115                 uint16 dec;
00116         };
00117         typedef PodVector<HScore>::type   Scores;
00118         typedef VarVec::iterator Pos;
00119         
00120         struct Order {
00121                 explicit Order(bool scoreHuang, bool scoreOnce) : decay(0), huang(scoreHuang), once(scoreOnce) {}
00122                 struct Compare {
00123                         explicit Compare(Order* o) : self(o) {}
00124                         bool operator()(Var v1, Var v2) const {
00125                                 return self->decayedScore(v1) > self->decayedScore(v2)
00126                                         || (self->score[v1].act == self->score[v2].act && v1 < v2);
00127                         }
00128                         Order* self; 
00129                 };
00130                 uint32  decayedScore(Var v) { return score[v].decay(decay, huang); }
00131                 int32   occ(Var v)   const  { return score[v].occ; }
00132                 void    inc(Literal p)      { score[p.var()].incAct(decay, huang, p.sign()); }
00133                 void    inc(Literal p, uint16 f) { if (f) { score[p.var()].decay(decay, huang); score[p.var()].act += f; } }
00134                 void    incOcc(Literal p)   {
00135                         if (!huang)score[p.var()].incOcc(p.sign());
00136                         else       score[p.var()].incAct(decay, true, p.sign());
00137                 }
00138                 int     compare(Var v1, Var v2) {
00139                         return int(decayedScore(v1)) - int(decayedScore(v2));
00140                 }
00141                 void    resetDecay();
00142                 Scores  score;        // For each var v score_[v] stores heuristic score of v
00143                 uint32  decay;        // "global" decay counter. Increased every decP_ decisions
00144                 bool    huang;        // Use Huang's scoring scheme (see: Jinbo Huang: "A Case for Simple SAT Solvers")
00145                 bool    once;
00146         private:
00147                 Order(const Order&);
00148                 Order& operator=(const Order&);
00149         }       order_; 
00150         VarVec  cache_;         // Caches the most active variables
00151         LitVec  freeLits_;      // Stores free variables of the last learnt conflict clause that is not sat
00152         LitVec  freeOtherLits_; // Stores free variables of the last other learnt nogood that is not sat
00153         uint32  topConflict_;   // Index into the array of learnt nogoods used when searching for conflict clauses that are not sat
00154         uint32  topOther_;      // Index into the array of learnt nogoods used when searching for other learnt nogoods that are not sat
00155         Var     front_;         // First variable whose truth-value is not already known - reset on backtracking
00156         Pos     cacheFront_;    // First unprocessed cache position - reset on backtracking
00157         uint32  cacheSize_;     // Cache at most cacheSize_ variables
00158         uint32  numVsids_;      // Number of consecutive vsids-based decisions
00159         uint32  maxBerkmin_;    // When searching for an open learnt constraint, check at most maxBerkmin_ candidates.
00160         TypeSet types_;         // When searching for an open learnt constraint, consider these types of nogoods.
00161         RNG     rng_;
00162 };
00163 
00165 
00174 class ClaspVmtf : public DecisionHeuristic {
00175 public:
00179         explicit ClaspVmtf(LitVec::size_type mtf = 8, const HeuParams& params = HeuParams());
00180         void startInit(const Solver& s);
00181         void endInit(Solver&);
00182         void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t);
00183         void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit);
00184         bool bump(const Solver& s, const WeightLitVec& lits, double adj);
00185         void simplify(const Solver&, LitVec::size_type);
00186         void undoUntil(const Solver&, LitVec::size_type);
00187         void updateVar(const Solver& s, Var v, uint32 n);
00188 protected:
00189         Literal doSelect(Solver& s);
00190 private:
00191         Literal selectRange(Solver& s, const Literal* first, const Literal* last);
00192         typedef std::list<Var> VarList;
00193         typedef VarList::iterator VarPos;
00194         struct VarInfo {
00195                 VarInfo(VarPos it) : pos_(it), activity_(0), occ_(0), decay_(0) { }
00196                 VarPos  pos_;       // position of var in var list
00197                 uint32  activity_;  // activity of var - initially 0
00198                 int32   occ_;       // which literal of var occurred more often in learnt constraints?
00199                 uint32  decay_;     // counter for lazy decaying activity
00200                 uint32& activity(uint32 globalDecay) {
00201                         if (uint32 x = (globalDecay - decay_)) {
00202                                 activity_ >>= (x<<1);
00203                                 decay_ = globalDecay;
00204                         }
00205                         return activity_;
00206                 }
00207         };
00208         typedef PodVector<VarInfo>::type Score;
00209         
00210         struct LessLevel {
00211                 LessLevel(const Solver& s, const Score& sc) : s_(s), sc_(sc) {}
00212                 bool operator()(Var v1, Var v2) const {
00213                         return s_.level(v1) < s_.level(v2) 
00214                                 || (s_.level(v1) == s_.level(v2) && sc_[v1].activity_ > sc_[v2].activity_);
00215                 }
00216                 bool operator()(Literal l1, Literal l2) const {
00217                         return (*this)(l1.var(), l2.var());
00218                 }
00219         private:
00220                 LessLevel& operator=(const LessLevel&);
00221                 const Solver& s_;
00222                 const Score&  sc_;
00223         };
00224         Score   score_; // For each var v score_[v] stores heuristic score of v
00225         VarList vars_;  // List of possible choices, initially ordered by MOMs-like score
00226         VarVec  mtf_;   // Vars to be moved to the front of vars_
00227         VarPos  front_; // Current front-position in var list - reset on backtracking 
00228         uint32  decay_; // "Global" decay counter. Increased every 512 decisions
00229         TypeSet types_; // Type of nogoods to score during resolution
00230         const LitVec::size_type MOVE_TO_FRONT;
00231 };
00232 
00234 
00237 struct VsidsScore {
00238         typedef VsidsScore SC;
00239         VsidsScore() : value(0.0) {}
00240         double get()                  const { return value; }
00241         bool   operator>(const SC& o) const { return value > o.value; }
00242         double inc(double f)                { return (value += f); }
00243         void   set(double f)                { value = f; }
00244         double value;
00245 };
00246 
00248 
00259 template <class ScoreType>
00260 class ClaspVsids_t : public DecisionHeuristic {
00261 public:
00265         explicit ClaspVsids_t(double d = 0.95, const HeuParams& params = HeuParams());
00266         void startInit(const Solver& s);
00267         void endInit(Solver&);
00268         void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t);
00269         void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit);
00270         bool bump(const Solver& s, const WeightLitVec& lits, double adj);
00271         void undoUntil(const Solver&, LitVec::size_type);
00272         void simplify(const Solver&, LitVec::size_type);
00273         void updateVar(const Solver& s, Var v, uint32 n);
00274 protected:
00275         Literal doSelect(Solver& s);
00276         virtual void initScores(Solver& s, bool moms);
00277         typedef typename PodVector<ScoreType>::type ScoreVec;
00278         typedef PodVector<int32>::type              OccVec;
00279         Literal selectRange(Solver& s, const Literal* first, const Literal* last);
00280         void updateVarActivity(Var v, double f = 1.0) {
00281                 double old = score_[v].get(), n = score_[v].inc((inc_*f));
00282                 if (n > 1e100) { normalize(); }
00283                 if (vars_.is_in_queue(v)) {
00284                         if (n >= old) { vars_.increase(v); }
00285                         else          { vars_.decrease(v); }
00286                 }
00287         }
00288         void incOcc(Literal p) { occ_[p.var()] += 1 - (int(p.sign()) << 1); }
00289         int  occ(Var v) const  { return occ_[v]; }
00290         void normalize();
00291         struct CmpScore {
00292                 explicit CmpScore(const ScoreVec& s) : sc_(s) {}
00293                 bool operator()(Var v1, Var v2) const { return sc_[v1] > sc_[v2]; }
00294         private:
00295                 CmpScore& operator=(const CmpScore&);
00296                 const ScoreVec& sc_;
00297         };
00298         typedef bk_lib::indexed_priority_queue<CmpScore> VarOrder;
00299         ScoreVec     score_;
00300         OccVec       occ_;
00301         VarOrder     vars_;
00302         const double decay_;
00303         double       inc_;
00304         TypeSet      types_;
00305 };
00306 typedef ClaspVsids_t<VsidsScore> ClaspVsids;
00307 
00309 
00312 struct DomScore {
00313         typedef DomScore SC;
00314         DomScore() : value(0.0), level(0), factor(1), domKey(UINT32_MAX) {}
00315         double get()                  const { return value; }
00316         bool   operator>(const SC& o) const { return (level > o.level) || (level == o.level && value > o.value); }
00317         bool   isDom()                const { return domKey != UINT32_MAX; }
00318         void   setDom(uint32 key)           { domKey = key; }
00319         double inc(double f)                { return (value += (f*factor)); }
00320         void   set(double f)                { value = f; }
00321         double value;  // activity as in VSIDS
00322         int16  level;  // priority level
00323         int16  factor; // factor used when bumping activity
00324         uint32 domKey; // index into dom-table if dom var       
00325 };
00326 
00328 
00335 class DomainHeuristic : public ClaspVsids_t<DomScore>
00336                       , private Constraint {
00337 public:
00338         typedef ClaspVsids_t<DomScore> BaseType;
00339         enum GlobalPreference { gpref_atom = 1, gpref_scc = 2, gpref_hcc = 4, gpref_disj = 8, gpref_min  = 16, gpref_show = 32 };
00340         enum GlobalModifier   { gmod_level = 1, gmod_spos = 2, gmod_true = 3, gmod_sneg  = 4, gmod_false = 5, gmod_max_value };   
00341         explicit DomainHeuristic(double d = 0.95, const HeuParams& params = HeuParams());
00342         ~DomainHeuristic();
00343         virtual void startInit(const Solver& s);
00344         using BaseType::endInit;
00345 protected:
00346         // base interface
00347         virtual Literal     doSelect(Solver& s);
00348         virtual void        initScores(Solver& s, bool moms);
00349         // Constraint interface
00350         virtual Constraint* cloneAttach(Solver&) { return 0; }
00351         virtual void        reason(Solver&, Literal, LitVec&){}
00352         virtual PropResult  propagate(Solver&, Literal, uint32&);
00353         virtual void        undoLevel(Solver& s);
00354         // own interface
00355         void detach();
00356 private:
00357         // parsing & init
00358         typedef SymbolTable::symbol_type    SymbolType;
00359         typedef PodVector<SymbolType>::type SymbolMap;
00360         class  DomMinimize;
00361         struct CmpSymbol;
00362         struct DomEntry {
00363                 enum Modifier { mod_factor = 0, mod_level = 1, mod_sign = 2, mod_tf = 3, mod_init = 4 };
00364                 DomEntry(const SymbolType* s, Modifier m = mod_init) : sym(s), mod(m), val(0), prio(0), sign(0) {}
00365                 bool     parse(const char*& mod);
00366                 ValueRep signValue() const {
00367                         if (mod == mod_sign) { return ValueRep(val); }
00368                         if (mod == mod_tf)   { return ValueRep(value_true + sign); }
00369                         return value_free;
00370                 }
00371                 const SymbolType* sym;    // domain symbol
00372                 Modifier          mod;    // type of modification
00373                 int16             val;    // value of modification
00374                 uint16            prio:15;// (optional) priority of modification
00375                 uint16            sign: 1;// sign in case of mod_tf
00376         };
00377         struct DomAction {
00378                 uint32 var:29; // dom var to be modified
00379                 uint32 mod: 2; // modification to apply
00380                 uint32 comp:1; // compound action?
00381                 uint32 undo;   // next action in undo list
00382                 int16  val;    // value to apply 
00383                 uint16 prio;   // prio of modification
00384         };
00385         struct DomPrio {
00386                 void    clear() { prio[0] = prio[1] = prio[2] = 0; }
00387                 uint16  operator[](unsigned i) const { return prio[i]; }
00388                 uint16& operator[](unsigned i)       { return prio[i]; }
00389                 uint16  prio[3];
00390         };
00391         struct Frame {
00392                 Frame(uint32 lev, uint32 h) : dl(lev), head(h) {}
00393                 uint32 dl;
00394                 uint32 head;
00395         };
00396         typedef PodVector<DomAction>::type ActionVec;
00397         typedef PodVector<DomPrio>::type   PrioVec;
00398         typedef PodVector<Frame>::type     FrameVec;
00399         static const char* const domKey_s;
00400         static const char* const domEnd_s;
00401         static bool match(const char*& in, const char* match);
00402         static bool matchDom(const char*& in, std::string& out);
00403         static bool matchInt(const char*& in, int& out);
00404         void        addAction(Solver& s, const SymbolType& pre, const DomEntry& e);
00405         void        addAction(Solver& s, Literal x, uint32 modf, int16 levVal);
00406         void        endInit(const DomEntry& e, const DomPrio& prio) { 
00407                 Var v = e.sym->lit.var();
00408                 if (e.val)                            { score_[v].value += e.val; }
00409                 if (score_[v].domKey < dPrios_.size()){ dPrios_[score_[v].domKey] = prio; }
00410         }
00411         void        pushUndo(Solver& s, uint32 actionId);
00412         void        applyAction(Solver& s, DomAction& act, uint16& oldPrio);
00413         Solver*   solver_;  // solver to which we are attached as a constraint
00414         LitVec*   minLits_; // optional: domain literals to minimize
00415         ActionVec actions_; // dynamic modifications
00416         PrioVec   dPrios_;  // dynamic priorities
00417         FrameVec  frames_;  // dynamic undo information
00418 };
00419 }
00420 #endif


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39