| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831 |
- /***********************************************************************************[SimpSolver.cc]
- MiniSat -- Copyright (c) 2006, Niklas Een, Niklas Sorensson
- Copyright (c) 2007-2010, Niklas Sorensson
- Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
-
- Maple_LCM, Based on MapleCOMSPS_DRUP -- Copyright (c) 2017, Mao Luo, Chu-Min LI, Fan Xiao: implementing a learnt clause minimisation approach
- Reference: M. Luo, C.-M. Li, F. Xiao, F. Manya, and Z. L. , “An effective learnt clause minimization approach for cdcl sat solvers,” in IJCAI-2017, 2017, pp. to–appear.
-
- Maple_LCM_Dist, Based on Maple_LCM -- Copyright (c) 2017, Fan Xiao, Chu-Min LI, Mao Luo: using a new branching heuristic called Distance at the beginning of search
-
-
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
- associated documentation files (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge, publish, distribute,
- sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all copies or
- substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
- NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
- OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- **************************************************************************************************/
- #include "mtl/Sort.h"
- #include "simp/SimpSolver.h"
- #include "utils/System.h"
- using namespace Minisat;
- //=================================================================================================
- // Options:
- static const char* _cat = "SIMP";
- static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false);
- static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false);
- static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true);
- static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0);
- static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX));
- static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX));
- static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false));
- //=================================================================================================
- // Constructor/Destructor:
- SimpSolver::SimpSolver() :
- parsing (false)
- , grow (opt_grow)
- , clause_lim (opt_clause_lim)
- , subsumption_lim (opt_subsumption_lim)
- , simp_garbage_frac (opt_simp_garbage_frac)
- , use_asymm (opt_use_asymm)
- , use_rcheck (opt_use_rcheck)
- , use_elim (opt_use_elim)
- , merges (0)
- , asymm_lits (0)
- , eliminated_vars (0)
- , elimorder (1)
- , use_simplification (true)
- , occurs (ClauseDeleted(ca))
- , elim_heap (ElimLt(n_occ))
- , bwdsub_assigns (0)
- , n_touched (0)
- {
- vec<Lit> dummy(1,lit_Undef);
- ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
- bwdsub_tmpunit = ca.alloc(dummy);
- remove_satisfied = false;
- }
- SimpSolver::~SimpSolver()
- {
- }
- Var SimpSolver::newVar(bool sign, bool dvar) {
- Var v = Solver::newVar(sign, dvar);
- frozen .push((char)false);
- eliminated.push((char)false);
- if (use_simplification){
- n_occ .push(0);
- n_occ .push(0);
- occurs .init(v);
- touched .push(0);
- elim_heap .insert(v);
- }
- return v; }
- lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
- {
- vec<Var> extra_frozen;
- lbool result = l_True;
- do_simp &= use_simplification;
- if (do_simp){
- // Assumptions must be temporarily frozen to run variable elimination:
- for (int i = 0; i < assumptions.size(); i++){
- Var v = var(assumptions[i]);
- // If an assumption has been eliminated, remember it.
- assert(!isEliminated(v));
- if (!frozen[v]){
- // Freeze and store.
- setFrozen(v, true);
- extra_frozen.push(v);
- } }
- result = lbool(eliminate(turn_off_simp));
- }
- if (result == l_True)
- result = Solver::solve_();
- else if (verbosity >= 1)
- printf("c ===============================================================================\n");
- if (result == l_True)
- extendModel();
- if (do_simp)
- // Unfreeze the assumptions that were frozen:
- for (int i = 0; i < extra_frozen.size(); i++)
- setFrozen(extra_frozen[i], false);
- return result;
- }
- bool SimpSolver::addClause_(vec<Lit>& ps)
- {
- #ifndef NDEBUG
- for (int i = 0; i < ps.size(); i++)
- assert(!isEliminated(var(ps[i])));
- #endif
- int nclauses = clauses.size();
- if (use_rcheck && implied(ps))
- return true;
- if (!Solver::addClause_(ps))
- return false;
- if (!parsing && drup_file) {
- #ifdef BIN_DRUP
- binDRUP('a', ps, drup_file);
- #else
- for (int i = 0; i < ps.size(); i++)
- fprintf(drup_file, "%i ", (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1));
- fprintf(drup_file, "0\n");
- #endif
- }
- if (use_simplification && clauses.size() == nclauses + 1){
- CRef cr = clauses.last();
- const Clause& c = ca[cr];
- // NOTE: the clause is added to the queue immediately and then
- // again during 'gatherTouchedClauses()'. If nothing happens
- // in between, it will only be checked once. Otherwise, it may
- // be checked twice unnecessarily. This is an unfortunate
- // consequence of how backward subsumption is used to mimic
- // forward subsumption.
- subsumption_queue.insert(cr);
- for (int i = 0; i < c.size(); i++){
- occurs[var(c[i])].push(cr);
- n_occ[toInt(c[i])]++;
- touched[var(c[i])] = 1;
- n_touched++;
- if (elim_heap.inHeap(var(c[i])))
- elim_heap.increase(var(c[i]));
- }
- }
- return true;
- }
- void SimpSolver::removeClause(CRef cr)
- {
- const Clause& c = ca[cr];
- if (use_simplification)
- for (int i = 0; i < c.size(); i++){
- n_occ[toInt(c[i])]--;
- updateElimHeap(var(c[i]));
- occurs.smudge(var(c[i]));
- }
- Solver::removeClause(cr);
- }
- bool SimpSolver::strengthenClause(CRef cr, Lit l)
- {
- Clause& c = ca[cr];
- assert(decisionLevel() == 0);
- assert(use_simplification);
- // FIX: this is too inefficient but would be nice to have (properly implemented)
- // if (!find(subsumption_queue, &c))
- subsumption_queue.insert(cr);
- if (drup_file){
- #ifdef BIN_DRUP
- binDRUP_strengthen(c, l, drup_file);
- #else
- for (int i = 0; i < c.size(); i++)
- if (c[i] != l) fprintf(drup_file, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
- fprintf(drup_file, "0\n");
- #endif
- }
- if (c.size() == 2){
- removeClause(cr);
- c.strengthen(l);
- }else{
- if (drup_file){
- #ifdef BIN_DRUP
- binDRUP('d', c, drup_file);
- #else
- fprintf(drup_file, "d ");
- for (int i = 0; i < c.size(); i++)
- fprintf(drup_file, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
- fprintf(drup_file, "0\n");
- #endif
- }
- detachClause(cr, true);
- c.strengthen(l);
- attachClause(cr);
- remove(occurs[var(l)], cr);
- n_occ[toInt(l)]--;
- updateElimHeap(var(l));
- }
- return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true;
- }
- // Returns FALSE if clause is always satisfied ('out_clause' should not be used).
- bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
- {
- merges++;
- out_clause.clear();
- bool ps_smallest = _ps.size() < _qs.size();
- const Clause& ps = ps_smallest ? _qs : _ps;
- const Clause& qs = ps_smallest ? _ps : _qs;
- for (int i = 0; i < qs.size(); i++){
- if (var(qs[i]) != v){
- for (int j = 0; j < ps.size(); j++)
- if (var(ps[j]) == var(qs[i]))
- if (ps[j] == ~qs[i])
- return false;
- else
- goto next;
- out_clause.push(qs[i]);
- }
- next:;
- }
- for (int i = 0; i < ps.size(); i++)
- if (var(ps[i]) != v)
- out_clause.push(ps[i]);
- return true;
- }
- // Returns FALSE if clause is always satisfied.
- bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
- {
- merges++;
- bool ps_smallest = _ps.size() < _qs.size();
- const Clause& ps = ps_smallest ? _qs : _ps;
- const Clause& qs = ps_smallest ? _ps : _qs;
- const Lit* __ps = (const Lit*)ps;
- const Lit* __qs = (const Lit*)qs;
- size = ps.size()-1;
- for (int i = 0; i < qs.size(); i++){
- if (var(__qs[i]) != v){
- for (int j = 0; j < ps.size(); j++)
- if (var(__ps[j]) == var(__qs[i]))
- if (__ps[j] == ~__qs[i])
- return false;
- else
- goto next;
- size++;
- }
- next:;
- }
- return true;
- }
- void SimpSolver::gatherTouchedClauses()
- {
- if (n_touched == 0) return;
- int i,j;
- for (i = j = 0; i < subsumption_queue.size(); i++)
- if (ca[subsumption_queue[i]].mark() == 0)
- ca[subsumption_queue[i]].mark(2);
- for (i = 0; i < touched.size(); i++)
- if (touched[i]){
- const vec<CRef>& cs = occurs.lookup(i);
- for (j = 0; j < cs.size(); j++)
- if (ca[cs[j]].mark() == 0){
- subsumption_queue.insert(cs[j]);
- ca[cs[j]].mark(2);
- }
- touched[i] = 0;
- }
- for (i = 0; i < subsumption_queue.size(); i++)
- if (ca[subsumption_queue[i]].mark() == 2)
- ca[subsumption_queue[i]].mark(0);
- n_touched = 0;
- }
- bool SimpSolver::implied(const vec<Lit>& c)
- {
- assert(decisionLevel() == 0);
- trail_lim.push(trail.size());
- for (int i = 0; i < c.size(); i++)
- if (value(c[i]) == l_True){
- cancelUntil(0);
- return true;
- }else if (value(c[i]) != l_False){
- assert(value(c[i]) == l_Undef);
- uncheckedEnqueue(~c[i]);
- }
- bool result = propagate() != CRef_Undef;
- cancelUntil(0);
- return result;
- }
- // Backward subsumption + backward subsumption resolution
- bool SimpSolver::backwardSubsumptionCheck(bool verbose)
- {
- int cnt = 0;
- int subsumed = 0;
- int deleted_literals = 0;
- assert(decisionLevel() == 0);
- while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
- // Empty subsumption queue and return immediately on user-interrupt:
- if (asynch_interrupt){
- subsumption_queue.clear();
- bwdsub_assigns = trail.size();
- break; }
- // Check top-level assignments by creating a dummy clause and placing it in the queue:
- if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
- Lit l = trail[bwdsub_assigns++];
- ca[bwdsub_tmpunit][0] = l;
- ca[bwdsub_tmpunit].calcAbstraction();
- subsumption_queue.insert(bwdsub_tmpunit); }
- CRef cr = subsumption_queue.peek(); subsumption_queue.pop();
- Clause& c = ca[cr];
- if (c.mark()) continue;
- if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
- printf("c subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
- assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point.
- // Find best variable to scan:
- Var best = var(c[0]);
- for (int i = 1; i < c.size(); i++)
- if (occurs[var(c[i])].size() < occurs[best].size())
- best = var(c[i]);
- // Search all candidates:
- vec<CRef>& _cs = occurs.lookup(best);
- CRef* cs = (CRef*)_cs;
- for (int j = 0; j < _cs.size(); j++)
- if (c.mark())
- break;
- else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){
- Lit l = c.subsumes(ca[cs[j]]);
- if (l == lit_Undef)
- subsumed++, removeClause(cs[j]);
- else if (l != lit_Error){
- deleted_literals++;
- if (!strengthenClause(cs[j], ~l))
- return false;
- // Did current candidate get deleted from cs? Then check candidate at index j again:
- if (var(l) == best)
- j--;
- }
- }
- }
- return true;
- }
- bool SimpSolver::asymm(Var v, CRef cr)
- {
- Clause& c = ca[cr];
- assert(decisionLevel() == 0);
- if (c.mark() || satisfied(c)) return true;
- trail_lim.push(trail.size());
- Lit l = lit_Undef;
- for (int i = 0; i < c.size(); i++)
- if (var(c[i]) != v){
- if (value(c[i]) != l_False)
- uncheckedEnqueue(~c[i]);
- }else
- l = c[i];
- if (propagate() != CRef_Undef){
- cancelUntil(0);
- asymm_lits++;
- if (!strengthenClause(cr, l))
- return false;
- }else
- cancelUntil(0);
- return true;
- }
- bool SimpSolver::asymmVar(Var v)
- {
- assert(use_simplification);
- const vec<CRef>& cls = occurs.lookup(v);
- if (value(v) != l_Undef || cls.size() == 0)
- return true;
- for (int i = 0; i < cls.size(); i++)
- if (!asymm(v, cls[i]))
- return false;
- return backwardSubsumptionCheck();
- }
- static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
- {
- elimclauses.push(toInt(x));
- elimclauses.push(1);
- }
- static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c)
- {
- int first = elimclauses.size();
- int v_pos = -1;
- // Copy clause to elimclauses-vector. Remember position where the
- // variable 'v' occurs:
- for (int i = 0; i < c.size(); i++){
- elimclauses.push(toInt(c[i]));
- if (var(c[i]) == v)
- v_pos = i + first;
- }
- assert(v_pos != -1);
- // Swap the first literal with the 'v' literal, so that the literal
- // containing 'v' will occur first in the clause:
- uint32_t tmp = elimclauses[v_pos];
- elimclauses[v_pos] = elimclauses[first];
- elimclauses[first] = tmp;
- // Store the length of the clause last:
- elimclauses.push(c.size());
- }
- bool SimpSolver::eliminateVar(Var v)
- {
- assert(!frozen[v]);
- assert(!isEliminated(v));
- assert(value(v) == l_Undef);
- // Split the occurrences into positive and negative:
- //
- const vec<CRef>& cls = occurs.lookup(v);
- vec<CRef> pos, neg;
- for (int i = 0; i < cls.size(); i++)
- (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
- // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
- // clause must exceed the limit on the maximal clause size (if it is set):
- //
- int cnt = 0;
- int clause_size = 0;
- for (int i = 0; i < pos.size(); i++)
- for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
- (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
- return true;
- // Delete and store old clauses:
- eliminated[v] = true;
- setDecisionVar(v, false);
- eliminated_vars++;
- if (pos.size() > neg.size()){
- for (int i = 0; i < neg.size(); i++)
- mkElimClause(elimclauses, v, ca[neg[i]]);
- mkElimClause(elimclauses, mkLit(v));
- }else{
- for (int i = 0; i < pos.size(); i++)
- mkElimClause(elimclauses, v, ca[pos[i]]);
- mkElimClause(elimclauses, ~mkLit(v));
- }
- // Produce clauses in cross product:
- vec<Lit>& resolvent = add_tmp;
- for (int i = 0; i < pos.size(); i++)
- for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent))
- return false;
- for (int i = 0; i < cls.size(); i++)
- removeClause(cls[i]);
- // Free occurs list for this variable:
- occurs[v].clear(true);
-
- // Free watchers lists for this variable, if possible:
- watches_bin[ mkLit(v)].clear(true);
- watches_bin[~mkLit(v)].clear(true);
- watches[ mkLit(v)].clear(true);
- watches[~mkLit(v)].clear(true);
- return backwardSubsumptionCheck();
- }
- bool SimpSolver::substitute(Var v, Lit x)
- {
- assert(!frozen[v]);
- assert(!isEliminated(v));
- assert(value(v) == l_Undef);
- if (!ok) return false;
- eliminated[v] = true;
- setDecisionVar(v, false);
- const vec<CRef>& cls = occurs.lookup(v);
-
- vec<Lit>& subst_clause = add_tmp;
- for (int i = 0; i < cls.size(); i++){
- Clause& c = ca[cls[i]];
- subst_clause.clear();
- for (int j = 0; j < c.size(); j++){
- Lit p = c[j];
- subst_clause.push(var(p) == v ? x ^ sign(p) : p);
- }
- if (!addClause_(subst_clause))
- return ok = false;
- removeClause(cls[i]);
- }
- return true;
- }
- void SimpSolver::extendModel()
- {
- int i, j;
- Lit x;
- for (i = elimclauses.size()-1; i > 0; i -= j){
- for (j = elimclauses[i--]; j > 1; j--, i--)
- if (modelValue(toLit(elimclauses[i])) != l_False)
- goto next;
- x = toLit(elimclauses[i]);
- model[var(x)] = lbool(!sign(x));
- next:;
- }
- }
- // Almost duplicate of Solver::removeSatisfied. Didn't want to make the base method 'virtual'.
- void SimpSolver::removeSatisfied()
- {
- int i, j;
- for (i = j = 0; i < clauses.size(); i++){
- const Clause& c = ca[clauses[i]];
- if (c.mark() == 0)
- if (satisfied(c))
- removeClause(clauses[i]);
- else
- clauses[j++] = clauses[i];
- }
- clauses.shrink(i - j);
- }
- // The technique and code are by the courtesy of the GlueMiniSat team. Thank you!
- // It helps solving certain types of huge problems tremendously.
- bool SimpSolver::eliminate(bool turn_off_elim)
- {
- bool res = true;
- int iter = 0;
- int n_cls, n_cls_init, n_vars;
- if (nVars() == 0) goto cleanup; // User disabling preprocessing.
- // Get an initial number of clauses (more accurately).
- if (trail.size() != 0) removeSatisfied();
- n_cls_init = nClauses();
- res = eliminate_(); // The first, usual variable elimination of MiniSat.
- if (!res) goto cleanup;
- n_cls = nClauses();
- n_vars = nFreeVars();
- printf("c Reduced to %d vars, %d cls (grow=%d)\n", n_vars, n_cls, grow);
- if ((double)n_cls / n_vars >= 10 || n_vars < 10000){
- printf("c No iterative elimination performed. (vars=%d, c/v ratio=%.1f)\n", n_vars, (double)n_cls / n_vars);
- goto cleanup; }
- grow = grow ? grow * 2 : 8;
- for (; grow < 10000; grow *= 2){
- // Rebuild elimination variable heap.
- for (int i = 0; i < clauses.size(); i++){
- const Clause& c = ca[clauses[i]];
- for (int j = 0; j < c.size(); j++)
- if (!elim_heap.inHeap(var(c[j])))
- elim_heap.insert(var(c[j]));
- else
- elim_heap.update(var(c[j])); }
- int n_cls_last = nClauses();
- int n_vars_last = nFreeVars();
- res = eliminate_();
- if (!res || n_vars_last == nFreeVars()) break;
- iter++;
- int n_cls_now = nClauses();
- int n_vars_now = nFreeVars();
- double cl_inc_rate = (double)n_cls_now / n_cls_last;
- double var_dec_rate = (double)n_vars_last / n_vars_now;
- printf("c Reduced to %d vars, %d cls (grow=%d)\n", n_vars_now, n_cls_now, grow);
- printf("c cl_inc_rate=%.3f, var_dec_rate=%.3f\n", cl_inc_rate, var_dec_rate);
- if (n_cls_now > n_cls_init || cl_inc_rate > var_dec_rate) break;
- }
- printf("c No. effective iterative eliminations: %d\n", iter);
- cleanup:
- touched .clear(true);
- occurs .clear(true);
- n_occ .clear(true);
- elim_heap.clear(true);
- subsumption_queue.clear(true);
- use_simplification = false;
- remove_satisfied = true;
- ca.extra_clause_field = false;
- // Force full cleanup (this is safe and desirable since it only happens once):
- rebuildOrderHeap();
- garbageCollect();
- return res;
- }
- bool SimpSolver::eliminate_()
- {
- if (!simplify())
- return false;
- else if (!use_simplification)
- return true;
- int trail_size_last = trail.size();
- // Main simplification loop:
- //
- while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){
- gatherTouchedClauses();
- // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
- if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
- !backwardSubsumptionCheck(true)){
- ok = false; goto cleanup; }
- // Empty elim_heap and return immediately on user-interrupt:
- if (asynch_interrupt){
- assert(bwdsub_assigns == trail.size());
- assert(subsumption_queue.size() == 0);
- assert(n_touched == 0);
- elim_heap.clear();
- goto cleanup; }
- // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
- for (int cnt = 0; !elim_heap.empty(); cnt++){
- Var elim = elim_heap.removeMin();
-
- if (asynch_interrupt) break;
- if (isEliminated(elim) || value(elim) != l_Undef) continue;
- if (verbosity >= 2 && cnt % 100 == 0)
- printf("c elimination left: %10d\r", elim_heap.size());
- if (use_asymm){
- // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again:
- bool was_frozen = frozen[elim];
- frozen[elim] = true;
- if (!asymmVar(elim)){
- ok = false; goto cleanup; }
- frozen[elim] = was_frozen; }
- // At this point, the variable may have been set by assymetric branching, so check it
- // again. Also, don't eliminate frozen variables:
- if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){
- ok = false; goto cleanup; }
- checkGarbage(simp_garbage_frac);
- }
- assert(subsumption_queue.size() == 0);
- }
- cleanup:
- // To get an accurate number of clauses.
- if (trail_size_last != trail.size())
- removeSatisfied();
- else{
- int i,j;
- for (i = j = 0; i < clauses.size(); i++)
- if (ca[clauses[i]].mark() == 0)
- clauses[j++] = clauses[i];
- clauses.shrink(i - j);
- }
- checkGarbage();
- if (verbosity >= 1 && elimclauses.size() > 0)
- printf("c | Eliminated clauses: %10.2f Mb |\n",
- double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
- return ok;
- }
- //=================================================================================================
- // Garbage Collection methods:
- void SimpSolver::relocAll(ClauseAllocator& to)
- {
- if (!use_simplification) return;
- // All occurs lists:
- //
- occurs.cleanAll();
- for (int i = 0; i < nVars(); i++){
- vec<CRef>& cs = occurs[i];
- for (int j = 0; j < cs.size(); j++)
- ca.reloc(cs[j], to);
- }
- // Subsumption queue:
- //
- for (int i = 0; i < subsumption_queue.size(); i++)
- ca.reloc(subsumption_queue[i], to);
- // Temporary clause:
- //
- ca.reloc(bwdsub_tmpunit, to);
- }
- void SimpSolver::garbageCollect()
- {
- // Initialize the next region to a size corresponding to the estimated utilization degree. This
- // is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
- to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
- relocAll(to);
- Solver::relocAll(to);
- if (verbosity >= 2)
- printf("c | Garbage collection: %12d bytes => %12d bytes |\n",
- ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
- to.moveTo(ca);
- }
|