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