1 //
2 // Copyright (c) 2006-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_SOLVER_STRATEGIES_H_INCLUDED
25 #define CLASP_SOLVER_STRATEGIES_H_INCLUDED
26 #ifdef _MSC_VER
27 #pragma once
28 #endif
29 
30 #include <clasp/constraint.h>
31 #include <clasp/util/misc_types.h>
32 
33 #if !defined(CLASP_ALIGN_BITFIELD)
34 #	if defined(EMSCRIPTEN)
35 // Force alignment of bitfield to T in order to prevent
36 // code-generation bug in emcc
37 // see: https://github.com/kripken/emscripten/issues/4540
38 #	define CLASP_ALIGN_BITFIELD(T) T : 0;
39 #	else
40 #	define CLASP_ALIGN_BITFIELD(T)
41 #	endif
42 #endif
43 
44 /*!
45  * \file
46  * \brief Contains strategies and options used to configure solvers and search.
47  */
48 namespace Clasp {
49 //! Implements clasp's configurable schedule-strategies.
50 /*!
51  * clasp currently supports the following basic strategies:
52  *  - geometric sequence  : X = n1 * n2^k   (k >= 0)
53  *  - arithmetic sequence : X = n1 + (n2*k) (k >= 0)
54  *  - fixed sequence      : X = n1 + (0*k)  (k >= 0)
55  *  - luby's sequence     : X = n1 * luby(k)(k >= 0)
56  *  .
57  * Furthermore, an inner-outer scheme can be applied to the selected sequence.
58  * In that case, the sequence is repeated every \<limit\>+j restarts, where
59  * \<limit\> is the initial outer-limit and j is the number of times the
60  * sequence was already repeated.
61  *
62  * \note For luby's seqeuence, j is not a repetition counter
63  * but the index where the sequence grows to the next power of two.
64  *
65  * \see Luby et al. "Optimal speedup of las vegas algorithms."
66  *
67  */
68 struct ScheduleStrategy {
69 public:
70 	//! Supported strategies.
71 	enum Type { Geometric = 0, Arithmetic = 1, Luby = 2, User = 3 };
72 
73 	ScheduleStrategy(Type t = Geometric, uint32 b = 100, double g = 1.5, uint32 o = 0);
74 	//! Creates luby's sequence with unit-length unit and optional outer limit.
75 	static ScheduleStrategy luby(uint32 unit, uint32 limit = 0)              { return ScheduleStrategy(Luby, unit, 0, limit);  }
76 	//! Creates geometric sequence base * (grow^k) with optional outer limit.
77 	static ScheduleStrategy geom(uint32 base, double grow, uint32 limit = 0) { return ScheduleStrategy(Geometric, base, grow, limit);  }
78 	//! Creates arithmetic sequence base + (add*k) with optional outer limit.
79 	static ScheduleStrategy arith(uint32 base, double add, uint32 limit = 0) { return ScheduleStrategy(Arithmetic, base, add, limit);  }
80 	//! Creates fixed sequence with length base.
fixedScheduleStrategy81 	static ScheduleStrategy fixed(uint32 base)                               { return ScheduleStrategy(Arithmetic, base, 0, 0);  }
noneScheduleStrategy82 	static ScheduleStrategy none()                                           { return ScheduleStrategy(Geometric, 0); }
defScheduleStrategy83 	static ScheduleStrategy def()                                            { return ScheduleStrategy(User, 0, 0.0); }
84 	uint64 current()  const;
disabledScheduleStrategy85 	bool   disabled() const { return base == 0; }
defaultedScheduleStrategy86 	bool   defaulted()const { return base == 0 && type == User; }
resetScheduleStrategy87 	void   reset()          { idx  = 0;         }
88 	uint64 next();
89 	void   advanceTo(uint32 idx);
90 	uint32 base : 30; // base of sequence (n1)
91 	uint32 type :  2; // type of basic sequence
92 	uint32 idx;       // current index into sequence
93 	uint32 len;       // length of sequence (0 if infinite) (once reached, sequence is repeated and len increased)
94 	float  grow;      // update parameter n2
95 };
96 //! Returns the idx'th value of the luby sequence.
97 uint32 lubyR(uint32 idx);
98 //! Returns the idx'th value of the geometric sequence with the given growth factor.
99 double growR(uint32 idx, double g);
100 //! Returns the idx'th value of the arithmetic sequence with the given addend.
101 double addR(uint32 idx, double a);
102 
103 class DecisionHeuristic;
104 //! Parameter-Object for grouping solver strategies.
105 struct SolverStrategies {
106 	//! Clasp's two general search strategies.
107 	enum SearchStrategy {
108 		use_learning = 0, //!< Analyze conflicts and learn First-1-UIP-clause.
109 		no_learning  = 1  //!< Don't analyze conflicts - chronological backtracking.
110 	};
111 	//! Default sign heuristic.
112 	enum SignHeu {
113 		sign_atom = 0, //!< Prefer negative literal for atoms.
114 		sign_pos  = 1, //!< Prefer positive literal.
115 		sign_neg  = 2, //!< Prefer negative literal.
116 		sign_rnd  = 3, //!< Prefer random literal.
117 	};
118 	//! Conflict clause minimization strategy.
119 	enum CCMinType {
120 		cc_local     = 0, //!< Basic algorithm.
121 		cc_recursive = 1, //!< Extended algorithm.
122 	};
123 	//! Antecedents to consider during conflict clause minimization.
124 	enum CCMinAntes {
125 		all_antes    = 0, //!< Consider all antecedents.
126 		short_antes  = 1, //!< Consider only short antecedents.
127 		binary_antes = 2, //!< Consider only binary antecedents.
128 		no_antes     = 3, //!< Don't minimize conflict clauses.
129 	};
130 	//! Simplifications for long conflict clauses.
131 	enum CCRepMode {
132 		cc_no_replace  = 0,//!< Don't replace literals in conflict clauses.
133 		cc_rep_decision= 1,//!< Replace conflict clause with decision sequence.
134 		cc_rep_uip     = 2,//!< Replace conflict clause with all uip clause.
135 		cc_rep_dynamic = 3,//!< Dynamically select between cc_rep_decision and cc_rep_uip.
136 	};
137 	//! Strategy for initializing watched literals in clauses.
138 	enum WatchInit  { watch_rand = 0, watch_first = 1, watch_least = 2 };
139 	//! Strategy for integrating new information in parallel solving.
140 	enum UpdateMode { update_on_propagate = 0, update_on_conflict  = 1 };
141 	enum LbdMode    { lbd_fixed = 0, lbd_updated_less = 1, lbd_update_glucose = 2, lbd_update_pseudo = 3 };
142 
143 	SolverStrategies();
144 	void prepare();
145 	//----- 32 bit ------------
146 	uint32    compress      : 16; /*!< If > 0, enable compression for learnt clauses of size > compress. */
147 	uint32    saveProgress  : 16; /*!< Enable progress saving if > 0. */
148 	//----- 32 bit ------------
149 	uint32    heuId         : 3;  /*!< Type of decision heuristic.   */
150 	uint32    reverseArcs   : 2;  /*!< Use "reverse-arcs" during learning if > 0. */
151 	uint32    otfs          : 2;  /*!< Enable "on-the-fly" subsumption if > 0. */
152 	uint32    updateLbd     : 2;  /*!< Update lbds of antecedents during conflict analysis (one of LbdMode). */
153 	uint32    ccMinAntes    : 2;  /*!< Antecedents to look at during conflict clause minimization. */
154 	uint32    ccRepMode     : 2;  /*!< One of CCRepMode. */
155 	uint32    ccMinRec      : 1;  /*!< If 1, use more expensive recursive nogood minimization.  */
156 	uint32    ccMinKeepAct  : 1;  /*!< Do not increase nogood activities during nogood minimization? */
157 	uint32    initWatches   : 2;  /*!< Initialize watches randomly in clauses. */
158 	uint32    upMode        : 1;  /*!< One of UpdateMode. */
159 	uint32    bumpVarAct    : 1;  /*!< Bump activities of vars implied by learnt clauses with small lbd. */
160 	uint32    search        : 1;  /*!< Current search strategy. */
161 	uint32    restartOnModel: 1;  /*!< Do a restart after each model. */
162 	uint32    signDef       : 2;  /*!< Default sign heuristic.        */
163 	uint32    signFix       : 1;  /*!< Disable all sign heuristics and always use default sign. */
164 	uint32    reserved      : 1;
165 	uint32    hasConfig     : 1;  /*!< Config applied to solver? */
166 	uint32    id            : 6;  /*!< Solver id - SHALL ONLY BE SET BY Shared Context! */
167 };
168 //! Parameter-Object for grouping additional heuristic options.
169 struct HeuParams {
170 	//! Strategy for scoring clauses not learnt by conflict analysis.
171 	enum ScoreOther { other_auto = 0u, other_no   = 1u, other_loop = 2u, other_all = 3u };
172 	//! Strategy for scoring during conflict analysis.
173 	enum Score      { score_auto = 0u, score_min  = 1u, score_set = 2u, score_multi_set = 3u };
174 	//! Global preference for domain heuristic.
175 	enum DomPref    { pref_atom  = 0u, pref_scc   = 1u, pref_hcc  = 2u, pref_disj = 4u, pref_min  = 8u, pref_show = 16u };
176 	//! Global modification for domain heuristic.
177 	enum DomMod     { mod_none   = 0u, mod_level  = 1u, mod_spos  = 2u, mod_true  = 3u, mod_sneg  = 4u, mod_false = 5u, mod_init = 6u, mod_factor = 7u };
178 	//! Values for dynamic decaying scheme.
179 	struct VsidsDecay {
180 		uint32 init: 10; /*!< Starting decay factor: 1/0.\<init\>. */
181 		uint32 bump:  7; /*!< Decay decrease value : \<bump\>/100. */
182 		uint32 freq: 15; /*!< Update decay factor every \<freq\> conflicts. */
183 	};
184 	HeuParams();
185 	uint32 param    : 16; /*!< Extra parameter for heuristic with meaning depending on type. */
186 	uint32 score    : 2;  /*!< Type of scoring during resolution. */
187 	uint32 other    : 2;  /*!< Consider other learnt nogoods in heuristic. */
188 	uint32 moms     : 1;  /*!< Use MOMS-score as top-level heuristic. */
189 	uint32 nant     : 1;  /*!< Prefer elements in NegAnte(P).      */
190 	uint32 huang    : 1;  /*!< Only for Berkmin.   */
191 	uint32 acids    : 1;  /*!< Only for Vsids/Dom. */
192 	uint32 domPref  : 5;  /*!< Default pref for doamin heuristic (set of DomPref). */
193 	uint32 domMod   : 3;  /*!< Default mod for domain heuristic (one of DomMod). */
194 	union {
195 		uint32     extra;
196 		VsidsDecay decay; /*!< Only for Vsids/Dom. */
197 	};
198 };
199 
200 struct OptParams {
201 	//! Strategy to use for optimization.
202 	enum Type {
203 		type_bb = 0, //!< Branch and bound based (model-guided) optimization.
204 		type_usc= 1, //!< Unsatisfiable-core based (core-guided) optimization.
205 	};
206 	//! Algorithm for model-guided optimization.
207 	enum BBAlgo {
208 		bb_lin  = 0u, //!< Linear branch and bound with fixed step of size 1.
209 		bb_hier = 1u, //!< Hierarchical branch and bound with fixed step of size 1.
210 		bb_inc  = 2u, //!< Hierarchical branch and bound with increasing steps.
211 		bb_dec  = 3u, //!< Hierarchical branch and bound with decreasing steps.
212 	};
213 	//! Algorithm for core-guided optimization.
214 	enum UscAlgo {
215 		usc_oll  = 0u, //!< OLL with possibly multiple cardinality constraints per core.
216 		usc_one  = 1u, //!< ONE with one cardinality constraints per core.
217 		usc_k    = 2u, //!< K with bounded cardinality constraints of size 2 * (K+1).
218 		usc_pmr  = 3u, //!< PMRES with clauses.
219 	};
220 	//! Additional tactics for core-guided optimization.
221 	enum UscOption {
222 		usc_disjoint = 1u, //!< Enable (disjoint) preprocessing.
223 		usc_succinct = 2u, //!< Do not add redundant constraints.
224 		usc_stratify = 4u, //!< Enable stratification for weighted optimization.
225 	};
226 	//! Strategy for unsatisfiable-core shrinking.
227 	enum UscTrim {
228 		usc_trim_lin = 1u, //!< Shrinking with linear search SAT->UNSAT.
229 		usc_trim_inv = 2u, //!< Shrinking with inverse linear search UNSAT->SAT.
230 		usc_trim_bin = 3u, //!< Shrinking with binary search SAT->UNSAT.
231 		usc_trim_rgs = 4u, //!< Shrinking with repeated geometric sequence until UNSAT.
232 		usc_trim_exp = 5u, //!< Shrinking with exponential search until UNSAT.
233 		usc_trim_min = 6u, //!< Shrinking with linear search for subset minimal core.
234 	};
235 	//! Heuristic options common to all optimization strategies.
236 	enum Heuristic {
237 		heu_sign  = 1,  //!< Use optimize statements in sign heuristic.
238 		heu_model = 2,  //!< Apply model heuristic when optimizing.
239 	};
240 	OptParams(Type st = type_bb);
supportsSplittingOptParams241 	bool supportsSplitting()    const { return type != type_usc; }
hasOptionOptParams242 	bool hasOption(UscOption o) const { return (opts & uint32(o)) != 0u; }
hasOptionOptParams243 	bool hasOption(Heuristic h) const { return (heus & uint32(h)) != 0u; }
244 	uint32 type : 1; /*!< Optimization strategy (see Type).*/
245 	uint32 heus : 2; /*!< Set of Heuristic values. */
246 	uint32 algo : 2; /*!< Optimization algorithm (see BBAlgo/UscAlgo). */
247 	uint32 trim : 3; /*!< Unsatisfiable-core shrinking (0=no shrinking). */
248 	uint32 opts : 4; /*!< Set of usc options. */
249 	uint32 tLim : 5; /*!< Limit core shrinking to 2^tLim conflicts (0=no limit). */
250 	uint32 kLim :15; /*!< Limit for algorithm K (0=dynamic limit). */
251 };
252 
253 //! Parameter-Object for configuring a solver.
254 struct SolverParams : SolverStrategies  {
255 	//! Supported forget options.
256 	enum Forget { forget_heuristic = 1u, forget_signs = 2u, forget_activities = 4u, forget_learnts = 8u };
257 	SolverParams();
258 	uint32 prepare();
forgetHeuristicSolverParams259 	inline bool forgetHeuristic() const { return (forgetSet & uint32(forget_heuristic))  != 0; }
forgetSignsSolverParams260 	inline bool forgetSigns()     const { return (forgetSet & uint32(forget_signs))      != 0; }
forgetActivitiesSolverParams261 	inline bool forgetActivities()const { return (forgetSet & uint32(forget_activities)) != 0; }
forgetLearntsSolverParams262 	inline bool forgetLearnts()   const { return (forgetSet & uint32(forget_learnts))    != 0; }
setIdSolverParams263 	SolverParams& setId(uint32 sId)     { id = sId; return *this; }
264 	HeuParams heuristic;  /*!< Parameters for decision heuristic. */
265 	OptParams opt;        /*!< Parameters for optimization.       */
266 	// 64-bit
267 	uint32 seed;           /*!< Seed for the random number generator.  */
268 	uint32 lookOps   : 16; /*!< Max. number of lookahead operations (0: no limit). */
269 	uint32 lookType  : 2;  /*!< Type of lookahead operations. */
270 	uint32 loopRep   : 2;  /*!< How to represent loops? */
271 	uint32 acycFwd   : 1;  /*!< Disable backward propagation in acyclicity checker. */
272 	uint32 forgetSet : 4;  /*!< What to forget on (incremental step). */
273 	uint32 reserved  : 7;
274 };
275 
276 typedef Range<uint32> Range32;
277 
278 //! Aggregates restart-parameters to configure restarts during search.
279 /*!
280  * \see ScheduleStrategy
281  */
282 struct RestartParams {
283 	RestartParams();
284 	enum SeqUpdate { seq_continue = 0, seq_repeat = 1, seq_disable = 2 };
285 	uint32    prepare(bool withLookback);
286 	void      disable();
dynamicRestartParams287 	bool      dynamic() const { return dynRestart != 0; }
localRestartParams288 	bool      local()   const { return cntLocal   != 0; }
updateRestartParams289 	SeqUpdate update()  const { return static_cast<SeqUpdate>(upRestart); }
290 	ScheduleStrategy sched;  /**< Restart schedule to use. */
291 	float  blockScale;       /**< Scaling factor for blocking restarts. */
292 	uint32 blockWindow: 16;  /**< Size of moving assignment average for blocking restarts (0: disable). */
293 	uint32 blockFirst : 16;  /**< Enable blocking restarts after blockFirst conflicts. */
294 	CLASP_ALIGN_BITFIELD(uint32)
295 	uint32 counterRestart:16;/**< Apply counter implication bump every counterRestart restarts (0: disable). */
296 	uint32 counterBump:16;   /**< Bump factor for counter implication restarts. */
297 	CLASP_ALIGN_BITFIELD(uint32)
298 	uint32 shuffle    :14;   /**< Shuffle program after shuffle restarts (0: disable). */
299 	uint32 shuffleNext:14;   /**< Re-Shuffle program every shuffleNext restarts (0: disable). */
300 	uint32 upRestart  : 2;   /**< How to update restart sequence after a model was found (one of SeqUpdate). */
301 	uint32 cntLocal   : 1;   /**< Count conflicts globally or relative to current branch? */
302 	uint32 dynRestart : 1;   /**< Dynamic restarts enabled? */
303 };
304 
305 //! Reduce strategy used during solving.
306 /*!
307  * A reduce strategy mainly consists of an algorithm and a scoring scheme
308  * for measuring "activity" of learnt constraints.
309  */
310 struct ReduceStrategy {
311 	//! Reduction algorithm to use during solving.
312 	enum Algorithm {
313 		reduce_linear = 0, //!< Linear algorithm from clasp-1.3.x.
314 		reduce_stable = 1, //!< Sort constraints by score but keep order in learnt db.
315 		reduce_sort   = 2, //!< Sort learnt db by score and remove fraction with lowest score.
316 		reduce_heap   = 3  //!< Similar to reduce_sort but only partially sorts learnt db.
317 	};
318 	//! Score to measure "activity" of learnt constraints.
319 	enum Score {
320 		score_act  = 0, //!< Activity only: how often constraint is used during conflict analysis.
321 		score_lbd  = 1, //!< Use literal block distance as activity.
322 		score_both = 2  //!< Use activity and lbd together.
323 	};
324 	//! Strategy for estimating size of problem.
325 	enum EstimateSize {
326 		est_dynamic         = 0, //!< Dynamically decide whether to use number of variables or constraints.
327 		est_con_complexity  = 1, //!< Measure size in terms of constraint complexities.
328 		est_num_constraints = 2, //!< Measure size in terms of number constraints.
329 		est_num_vars        = 3  //!< Measure size in terms of number variable.
330 	};
scoreActReduceStrategy331 	static uint32 scoreAct(const ConstraintScore& sc)  { return sc.activity(); }
scoreLbdReduceStrategy332 	static uint32 scoreLbd(const ConstraintScore& sc)  { return uint32(LBD_MAX+1)-sc.lbd(); }
scoreBothReduceStrategy333 	static uint32 scoreBoth(const ConstraintScore& sc) { return (sc.activity()+1) * scoreLbd(sc); }
compareReduceStrategy334 	static int    compare(Score sc, const ConstraintScore& lhs, const ConstraintScore& rhs) {
335 		int fs = 0;
336 		if      (sc == score_act) { fs = ((int)scoreAct(lhs)) - ((int)scoreAct(rhs)); }
337 		else if (sc == score_lbd) { fs = ((int)scoreLbd(lhs)) - ((int)scoreLbd(rhs)); }
338 		return fs != 0 ? fs : ((int)scoreBoth(lhs)) - ((int)scoreBoth(rhs));
339 	}
asScoreReduceStrategy340 	static uint32 asScore(Score sc, const Clasp::ConstraintScore& act) {
341 		if (sc == score_act)  { return scoreAct(act); }
342 		if (sc == score_lbd)  { return scoreLbd(act); }
343 		/*  sc == score_both*/{ return scoreBoth(act);}
344 	}
ReduceStrategyReduceStrategy345 	ReduceStrategy() : protect(0), glue(0), fReduce(75), fRestart(0), score(0), algo(0), estimate(0), noGlue(0) {
346 		static_assert(sizeof(ReduceStrategy) == sizeof(uint32), "invalid bitset");
347 	}
348 	uint32 protect : 7; /*!< Protect nogoods whose lbd was reduced and is now <= freeze. */
349 	uint32 glue    : 4; /*!< Don't remove nogoods with lbd <= glue.    */
350 	uint32 fReduce : 7; /*!< Fraction of nogoods to remove in percent. */
351 	uint32 fRestart: 7; /*!< Fraction of nogoods to remove on restart. */
352 	uint32 score   : 2; /*!< One of Score.                             */
353 	uint32 algo    : 2; /*!< One of Algorithm.                         */
354 	uint32 estimate: 2; /*!< How to estimate problem size in init.     */
355 	uint32 noGlue  : 1; /*!< Do not count glue clauses in limit.       */
356 };
357 
358 //! Aggregates parameters for the nogood deletion heuristic used during search.
359 /*!
360  * - S:delCond {yes,no}
361  * - no:del {0}[0]
362  * - no:del | delCond in {no}
363  * - deletion | delCond in {yes}
364  * - del-* | delCond in {yes}
365  * - {delCond=yes, del-grow=no, del-cfl=no}
366  * .
367  */
368 struct ReduceParams {
ReduceParamsReduceParams369 	ReduceParams() : cflSched(ScheduleStrategy::none()), growSched(ScheduleStrategy::def())
370 		, fInit(1.0f/3.0f)
371 		, fMax(3.0f)
372 		, fGrow(1.1f)
373 		, initRange(10, UINT32_MAX)
374 		, maxRange(UINT32_MAX)
375 		, memMax(0) {}
376 	void    disable();
377 	uint32  prepare(bool withLookback);
378 	Range32 sizeInit(const SharedContext& ctx) const;
379 	uint32  cflInit(const SharedContext& ctx)  const;
380 	uint32  getBase(const SharedContext& ctx)  const;
fReduceReduceParams381 	float   fReduce()  const { return strategy.fReduce / 100.0f; }
fRestartReduceParams382 	float   fRestart() const { return strategy.fRestart/ 100.0f; }
383 	static uint32 getLimit(uint32 base, double f, const Range<uint32>& r);
384 	ScheduleStrategy cflSched;   /**< Conflict-based deletion schedule.               */
385 	ScheduleStrategy growSched;  /**< Growth-based deletion schedule.                 */
386 	ReduceStrategy   strategy;   /**< Strategy to apply during nogood deletion.       */
387 	float            fInit;      /**< Initial limit. X = P*fInit clamped to initRange.*/
388 	float            fMax;       /**< Maximal limit. X = P*fMax  clamped to maxRange. */
389 	float            fGrow;      /**< Growth factor for db.                           */
390 	Range32          initRange;  /**< Allowed range for initial limit.                */
391 	uint32           maxRange;   /**< Allowed range for maximal limit: [initRange.lo,maxRange]*/
392 	uint32           memMax;     /**< Memory limit in MB (0 = no limit).              */
393 };
394 
395 //! Parameter-Object for grouping solve-related options.
396 /*!
397  * \ingroup enumerator
398  */
399 struct SolveParams {
400 	//! Creates a default-initialized object.
401 	/*!
402 	 * The following parameters are used:
403 	 * - restart      : quadratic: 100*1.5^k / no restarts after first solution
404 	 * - deletion     : initial size: vars()/3, grow factor: 1.1, max factor: 3.0, do not reduce on restart
405 	 * - randomization: disabled
406 	 * - randomProp   : 0.0 (disabled)
407 	 * .
408 	 */
409 	SolveParams();
410 	uint32  prepare(bool withLookback);
411 	bool    randomize(Solver& s) const;
412 	RestartParams restart;
413 	ReduceParams  reduce;
414 	uint32        randRuns:16; /*!< Number of initial randomized-runs. */
415 	uint32        randConf:16; /*!< Number of conflicts comprising one randomized-run. */
416 	float         randProb;    /*!< Use random heuristic with given probability ([0,1]) */
417 	struct FwdCheck {          /*!< Options for (partial checks in) DLP-solving; */
418 		uint32 highStep : 24;    /*!< Init/inc high level when reached. */
419 		uint32 highPct  :  7;    /*!< Check on low + (high - low) * highPct/100  */
420 		uint32 signDef  :  2;    /*!< Default sign heuristic for atoms in disjunctions. */
FwdCheckSolveParams::FwdCheck421 		FwdCheck() { std::memset(this, 0, sizeof(*this)); }
422 	}             fwdCheck;
423 };
424 
425 class SharedContext;
426 class SatPreprocessor;
427 
428 //! Parameters for (optional) Sat-preprocessing.
429 struct SatPreParams {
430 	enum Algo {
431 		sat_pre_no     = 0, /**< Disable sat-preprocessing.                            */
432 		sat_pre_ve     = 1, /**< Run variable elimination.                             */
433 		sat_pre_ve_bce = 2, /**< Run variable- and limited blocked clause elimination. */
434 		sat_pre_full   = 3, /**< Run variable- and full blocked clause elimination.    */
435 	};
SatPreParamsSatPreParams436 	SatPreParams() : type(0u), limIters(0u), limTime(0u), limFrozen(0u), limClause(4000u), limOcc(0u) {}
437 	uint32 type     :  2; /**< One of algo. */
438 	uint32 limIters : 11; /**< Max. number of iterations.                         (0=no limit)*/
439 	uint32 limTime  : 12; /**< Max. runtime in sec, checked after each iteration. (0=no limit)*/
440 	uint32 limFrozen:  7; /**< Run only if percent of frozen vars < maxFrozen.    (0=no limit)*/
441 	uint32 limClause: 16; /**< Run only if \#clauses \< (limClause*1000)          (0=no limit)*/
442 	uint32 limOcc   : 16; /**< Skip v, if \#occ(v) \>= limOcc && \#occ(~v) \>= limOcc.(0=no limit) */
clauseLimitSatPreParams443 	bool clauseLimit(uint32 nc)           const { return limClause && nc > (limClause*1000u); }
occLimitSatPreParams444 	bool occLimit(uint32 pos, uint32 neg) const { return limOcc && pos > (limOcc-1u) && neg > (limOcc-1u); }
bceSatPreParams445 	uint32 bce()                          const { return type != sat_pre_no ? type - 1 : 0; }
disableBceSatPreParams446 	void   disableBce()                         { type = std::min(type, uint32(sat_pre_ve));}
447 	static SatPreprocessor* create(const SatPreParams&);
448 };
449 
450 //! Parameters for a SharedContext object.
451 struct ContextParams {
452 	//! How to handle short learnt clauses.
453 	enum ShortMode  {
454 		short_implicit = 0, /*!< Share short learnt clauses via short implication graph. */
455 		short_explicit = 1, /*!< Do not use short implication graph. */
456 	};
457 	//! How to handle physical sharing of (explicit) constraints.
458 	enum ShareMode  {
459 		share_no      = 0, /*!< Do not physically share constraints (use copies instead). */
460 		share_problem = 1, /*!< Share problem constraints but copy learnt constraints.    */
461 		share_learnt  = 2, /*!< Copy problem constraints but share learnt constraints.    */
462 		share_all     = 3, /*!< Share all constraints.                                    */
463 		share_auto    = 4, /*!< Use share_no or share_all depending on number of solvers. */
464 	};
ContextParamsContextParams465 	ContextParams() : shareMode(share_auto), stats(0), shortMode(short_implicit), seed(1), hasConfig(0), cliConfig(0), cliId(0), cliMode(0) {}
466 	SatPreParams satPre;        /*!< Preprocessing options.                    */
467 	uint8        shareMode : 3; /*!< Physical sharing mode (one of ShareMode). */
468 	uint8        stats     : 2; /*!< See SharedContext::enableStats().         */
469 	uint8        shortMode : 1; /*!< One of ShortMode.                         */
470 	uint8        seed      : 1; /*!< Apply new seed when adding solvers.       */
471 	uint8        hasConfig : 1; /*!< Reserved for command-line interface.      */
472 	uint8        cliConfig;     /*!< Reserved for command-line interface.      */
473 	uint8        cliId;         /*!< Reserved for command-line interface.      */
474 	uint8        cliMode;       /*!< Reserved for command-line interface.      */
475 };
476 
477 //! Interface for configuring a SharedContext object and its associated solvers.
478 class Configuration {
479 public:
480 	typedef SolverParams  SolverOpts;
481 	typedef SolveParams   SearchOpts;
482 	typedef ContextParams CtxOpts;
483 	virtual ~Configuration();
484 	//! Prepares this configuration for the usage in the given context.
485 	virtual void               prepare(SharedContext&)    = 0;
486 	//! Returns the options for the shared context.
487 	virtual const CtxOpts&     context()            const = 0;
488 	//! Returns the number of solver options in this config.
489 	virtual uint32             numSolver()          const = 0;
490 	//! Returns the number of search options in this config.
491 	virtual uint32             numSearch()          const = 0;
492 	//! Returns the solver options for the i'th solver to be attached to the SharedContext.
493 	virtual const SolverOpts&  solver(uint32 i)     const = 0;
494 	//! Returns the search options for the i'th solver of the SharedContext.
495 	virtual const SearchOpts&  search(uint32 i)     const = 0;
496 	//! Returns the heuristic to be used in the i'th solver.
497 	/*!
498 	 * The function is called in Solver::startInit().
499 	 * \note The returned object is owned by the caller.
500 	 */
501 	virtual DecisionHeuristic* heuristic(uint32 i)  const = 0;
502 	//! Adds post propagators to the given solver.
503 	virtual bool               addPost(Solver& s)   const = 0;
504 	//! Returns the configuration with the given name or 0 if no such config exists.
505 	/*!
506 	 * The default implementation returns this
507 	 * if n is empty or one of "." or "/".
508 	 * Otherwise, 0 is returned.
509 	 */
510 	virtual Configuration*     config(const char* n);
511 };
512 
513 //! Base class for user-provided configurations.
514 class UserConfiguration : public Configuration {
515 public:
516 	//! Adds a lookahead post propagator to the given solver if requested.
517 	/*!
518 	 * The function adds a lookahead post propagator if indicated by
519 	 * the solver's SolverParams.
520 	 */
521 	virtual bool            addPost(Solver& s)   const;
522 	//! Returns the (modifiable) solver options for the i'th solver.
523 	virtual SolverOpts&     addSolver(uint32 i) = 0;
524 	//! Returns the (modifiable) search options for the i'th solver.
525 	virtual SearchOpts&     addSearch(uint32 i) = 0;
526 };
527 
528 //! Simple factory for decision heuristics.
529 struct Heuristic_t {
530 	enum Type { Default = 0, Berkmin = 1, Vsids = 2, Vmtf = 3, Domain = 4, Unit = 5, None = 6, User = 7  };
isLookbackHeuristic_t531 	static inline bool        isLookback(uint32 type) { return type >= (uint32)Berkmin && type < (uint32)Unit; }
532 	//! Default callback for creating decision heuristics.
533 	static DecisionHeuristic* create(Type t, const HeuParams& p);
534 };
535 
536 struct ProjectMode_t {
537 	enum Mode { Implicit = 0u, Output = 1u, Explicit = 2u };
538 };
539 typedef ProjectMode_t::Mode ProjectMode;
540 
541 //! Basic configuration for one or more SAT solvers.
542 class BasicSatConfig : public UserConfiguration, public ContextParams {
543 public:
544 	struct HeuristicCreator {
545 		virtual ~HeuristicCreator();
546 		virtual DecisionHeuristic* create(Heuristic_t::Type t, const HeuParams& p) = 0;
547 	};
548 
549 	BasicSatConfig();
550 	void               prepare(SharedContext&);
context()551 	const CtxOpts&     context()            const { return *this; }
numSolver()552 	uint32             numSolver()          const { return sizeVec(solver_); }
numSearch()553 	uint32             numSearch()          const { return sizeVec(search_); }
solver(uint32 i)554 	const SolverOpts&  solver(uint32 i)     const { return solver_[i % solver_.size() ]; }
search(uint32 i)555 	const SearchOpts&  search(uint32 i)     const { return search_[i % search_.size() ]; }
556 	DecisionHeuristic* heuristic(uint32 i)  const;
557 	SolverOpts&        addSolver(uint32 i);
558 	SearchOpts&        addSearch(uint32 i);
559 
560 	virtual void       reset();
561 	virtual void       resize(uint32 numSolver, uint32 numSearch);
562 	void               setHeuristicCreator(HeuristicCreator* hc, Ownership_t::Type = Ownership_t::Acquire);
563 private:
564 	typedef PodVector<SolverOpts>::type SolverVec;
565 	typedef PodVector<SearchOpts>::type SearchVec;
566 	typedef SingleOwnerPtr<HeuristicCreator> HeuFactory;
567 	SolverVec  solver_;
568 	SearchVec  search_;
569 	HeuFactory heu_;
570 };
571 
572 //! Base class for solving related events.
573 template <class T>
574 struct SolveEvent : Event_t<T> {
SolveEventSolveEvent575 	SolveEvent(const Solver& s, Event::Verbosity verb) : Event_t<T>(Event::subsystem_solve, verb), solver(&s) {}
576 	const Solver* solver;
577 };
578 struct Model;
579 //! Base class for handling results of a solve operation.
580 class ModelHandler {
581 public:
582 	virtual ~ModelHandler();
583 	virtual bool onModel(const Solver&, const Model&) = 0;
584 	virtual bool onUnsat(const Solver&, const Model&);
585 };
586 //! Type for storing the lower bound of a minimize statement.
587 struct LowerBound {
LowerBoundLowerBound588 	LowerBound() : level(0), bound(CLASP_WEIGHT_SUM_MIN) {}
resetLowerBound589 	void reset() { *this = LowerBound(); }
activeLowerBound590 	bool active() const { return bound != CLASP_WEIGHT_SUM_MIN; }
591 	uint32 level;
592 	wsum_t bound;
593 };
594 
595 }
596 #endif
597