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