1 // 2 // Copyright (c) 2009-2017 Benjamin Kaufmann 3 // 4 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 7 // of this software and associated documentation files (the "Software"), to 8 // deal in the Software without restriction, including without limitation the 9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 // sell copies of the Software, and to permit persons to whom the Software is 11 // furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in 14 // all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 // IN THE SOFTWARE. 23 // 24 #ifndef CLASP_LOOKAHEAD_H_INCLUDED 25 #define CLASP_LOOKAHEAD_H_INCLUDED 26 27 #ifdef _MSC_VER 28 #pragma once 29 #endif 30 31 /*! 32 * \file 33 * \brief Defines lookahead related types. 34 * 35 * Lookahead can be used as a post propagator (e.g. failed-literal detection) and 36 * optionally as an heuristic. 37 */ 38 39 #include <clasp/solver.h> 40 #include <clasp/constraint.h> 41 namespace Clasp { 42 /*! 43 * \addtogroup propagator 44 */ 45 //@{ 46 47 //! Type used to store lookahead-information for one variable. 48 struct VarScore { VarScoreVarScore49 VarScore() { clear(); } clearVarScore50 void clear() { std::memset(this, 0, sizeof(VarScore)); } 51 //! Mark literal p as dependent. setSeenVarScore52 void setSeen( Literal p ) { seen_ |= uint32(p.sign()) + 1; } 53 //! Is literal p dependent? seenVarScore54 bool seen(Literal p) const { return (seen_ & (uint32(p.sign())+1)) != 0; } 55 //! Is this var dependent? seenVarScore56 bool seen() const { return seen_ != 0; } 57 //! Mark literal p as tested during lookahead. setTestedVarScore58 void setTested( Literal p ) { tested_ |= uint32(p.sign()) + 1; } 59 //! Was literal p tested during lookahead? testedVarScore60 bool tested(Literal p) const { return (tested_ & (uint32(p.sign())+1)) != 0; } 61 //! Was some literal of this var tested? testedVarScore62 bool tested() const { return tested_ != 0; } 63 //! Were both literals of this var tested? testedBothVarScore64 bool testedBoth() const { return tested_ == 3; } 65 66 //! Sets the score for literal p to value and marks p as tested. setScoreVarScore67 void setScore(Literal p, LitVec::size_type value) { 68 if (value > (1U<<14)-1) value = (1U<<14)-1; 69 if (p.sign()) nVal_ = uint32(value); 70 else pVal_ = uint32(value); 71 setTested(p); 72 } 73 //! Sets the score of a dependent literal p to min(sc, current score). setDepScoreVarScore74 void setDepScore(Literal p, uint32 sc) { 75 if (!seen(p) || score(p) > sc) { 76 if (sc > (1U<<14)-1) sc = (1U<<14)-1; 77 if (p.sign()) nVal_ = std::min(uint32(nVal_-(nVal_==0)), sc); 78 else pVal_ = std::min(uint32(pVal_-(pVal_==0)), sc); 79 } 80 } 81 //! Returns the score for literal p. scoreVarScore82 uint32 score(Literal p) const { return p.sign() ? nVal_ : pVal_; } 83 //! Returns the scores of the two literals of a variable. 84 /*! 85 * \param[out] mx The maximum score. 86 * \param[out] mn The minimum score. 87 */ scoreVarScore88 void score(uint32& mx, uint32& mn) const { 89 if (nVal_ > pVal_) { 90 mx = nVal_; 91 mn = pVal_; 92 } 93 else { 94 mx = pVal_; 95 mn = nVal_; 96 } 97 } 98 //! Returns the sign of the literal that has the higher score. prefSignVarScore99 bool prefSign() const { return nVal_ > pVal_; } 100 nValVarScore101 uint32 nVal() const { return nVal_; } pValVarScore102 uint32 pVal() const { return pVal_; } 103 private: 104 uint32 pVal_ : 14; 105 uint32 nVal_ : 14; 106 uint32 seen_ : 2; 107 uint32 tested_: 2; 108 }; 109 110 //! A small helper class used to score the result of a lookahead operation. 111 struct ScoreLook { 112 enum Mode { score_max, score_max_min }; 113 typedef PodVector<VarScore>::type VarScores; /**< A vector of variable-scores */ ScoreLookScoreLook114 ScoreLook() : best(0), mode(score_max), addDeps(true), nant(false) {} validVarScoreLook115 bool validVar(Var v) const { return v < score.size(); } 116 void scoreLits(const Solver& s, const Literal* b, const Literal *e); 117 void clearDeps(); 118 uint32 countNant(const Solver& s, const Literal* b, const Literal *e) const; 119 bool greater(Var lhs, Var rhs)const; greaterMaxScoreLook120 bool greaterMax(Var x, uint32 max) const { 121 return score[x].nVal() > max || score[x].pVal() > max; 122 } greaterMaxMinScoreLook123 bool greaterMaxMin(Var lhs, uint32 max, uint32 min) const { 124 uint32 lhsMin, lhsMax; 125 score[lhs].score(lhsMax, lhsMin); 126 return lhsMin > min || (lhsMin == min && lhsMax > max); 127 } 128 VarScores score; //!< score[v] stores lookahead score of v 129 VarVec deps; //!< Tested vars and those that follow from them. 130 VarType types; //!< Var types to consider. 131 Var best; //!< Var with best score among those in deps. 132 Mode mode; //!< Score mode to apply. 133 bool addDeps;//!< Add/score dependent vars? 134 bool nant; //!< Score only atoms in NegAnte(P)? 135 }; 136 137 class UnitHeuristic; 138 139 //! Lookahead extends propagation with failed-literal detection. 140 /*! 141 * The class provides different kinds of one-step lookahead. 142 * Atom- and body-lookahead are uniform lookahead types, where 143 * either only atoms or bodies are tested. Hybrid-lookahead tests 144 * both types of vars but each only in a single phase. I.e. atoms 145 * are only tested negatively while bodies are tested positively. 146 */ 147 class Lookahead : public PostPropagator { 148 public: 149 //! Set of parameters to configure lookahead. 150 struct Params { typeParams151 Params(VarType t = Var_t::Atom) : type(t), lim(0), topLevelImps(true), restrictNant(false) {} lookaheadParams152 Params& lookahead(VarType t){ type = t; return *this; } addImpsParams153 Params& addImps(bool b) { topLevelImps = b; return *this; } nantParams154 Params& nant(bool b) { restrictNant = b; return *this; } limitParams155 Params& limit(uint32 x) { lim = x; return *this; } 156 VarType type; 157 uint32 lim; 158 bool topLevelImps; 159 bool restrictNant; 160 }; isType(uint32 t)161 static bool isType(uint32 t) { return t != 0 && t <= Var_t::Hybrid; } 162 /*! 163 * \param p Lookahead parameters to use. 164 */ 165 explicit Lookahead(const Params& p); 166 ~Lookahead(); 167 168 bool init(Solver& s); 169 //! Clears the lookahead list. 170 void clear(); 171 //! Returns true if lookahead list is empty. empty()172 bool empty() const { return head()->next == head_id; } 173 //! Adds literal p to the lookahead list. 174 void append(Literal p, bool testBoth); 175 //! Executes a single-step lookahead on all vars in the loookahead list. 176 bool propagateFixpoint(Solver& s, PostPropagator*); 177 //! Returns PostPropagator::priority_reserved_look. 178 uint32 priority() const; 179 void destroy(Solver* s, bool detach); 180 ScoreLook score; //!< State of last lookahead operation. 181 //! Returns "best" literal w.r.t scoring of last lookahead or lit_true() if no such literal exists. 182 Literal heuristic(Solver& s); 183 void detach(Solver& s); hasLimit()184 bool hasLimit() const { return limit_ != 0; } 185 protected: 186 bool propagateLevel(Solver& s); // called by propagate 187 void undoLevel(Solver& s); 188 bool test(Solver& s, Literal p); 189 private: 190 typedef uint32 NodeId; 191 enum { head_id = NodeId(0), undo_id = NodeId(1) }; 192 struct LitNode { LitNodeLitNode193 LitNode(Literal x) : lit(x), next(UINT32_MAX) {} 194 Literal lit; 195 NodeId next; 196 }; 197 typedef PodVector<NodeId>::type UndoStack; 198 typedef PodVector<LitNode>::type LookList; 199 typedef UnitHeuristic* HeuPtr; 200 void splice(NodeId n); node(NodeId n)201 LitNode* node(NodeId n) { return &nodes_[n]; } head()202 LitNode* head() { return &nodes_[head_id]; } // head of circular candidate list undo()203 LitNode* undo() { return &nodes_[undo_id]; } // head of undo list 204 bool checkImps(Solver& s, Literal p); head()205 const LitNode* head() const { return &nodes_[head_id]; } 206 LookList nodes_; // list of literals to test 207 UndoStack saved_; // stack of undo lists 208 LitVec imps_; // additional top-level implications 209 NodeId last_; // last candidate in list; invariant: node(last_)->next == head_id; 210 NodeId pos_; // current lookahead start position 211 uint32 top_; // size of top-level 212 uint32 limit_; // stop lookahead after this number of applications 213 }; 214 //@} 215 216 //! Heuristic that uses the results of lookahead. 217 /*! 218 * \ingroup heuristic 219 * The heuristic uses a Lookahead post propagator to select a literal with the highest score, 220 * where the score is determined by counting assignments made during 221 * failed-literal detection. For hybrid_lookahead, the heuristic selects the literal that 222 * derived the most literals. On the other hand, for uniform_lookahead the heuristic is similar to 223 * the smodels lookahead heuristic and selects the literal that maximizes the minimum. 224 * \see Patrik Simons: "Extending and Implementing the Stable Model Semantics" for a 225 * detailed description of the lookahead heuristic. 226 * 227 * \note The heuristic might itself apply some lookahead but only on variables that 228 * did not fail in a previous call to Lookahead::propagateFixpoint(). I.e. if 229 * priorities are correct for all post propagators in s, the lookahead operations can't fail. 230 * 231 * \note If no Lookahead post propagator exists in the solver, the heuristic selects the first free variable! 232 */ 233 class UnitHeuristic : public SelectFirst { 234 public: 235 UnitHeuristic(); 236 //! Decorates the heuristic given in other with temporary lookahead. 237 static UnitHeuristic* restricted(DecisionHeuristic* other); 238 void endInit(Solver& /* s */); 239 Literal doSelect(Solver& s); 240 }; 241 242 } 243 #endif 244