--- solvers/glucose30/core/Solver.h +++ solvers/glucose30/core/Solver.h @@ -29,6 +29,9 @@ #ifndef Glucose30_Solver_h #define Glucose30_Solver_h +#include +#include +#include #include "glucose30/mtl/Vec.h" #include "glucose30/mtl/Heap.h" #include "glucose30/mtl/Alg.h" @@ -182,7 +185,22 @@ uint64_t nbRemovedClauses,nbReducedClauses,nbDL2,nbBin,nbUn,nbReduceDB,solves, starts, decisions, rnd_decisions, propagations, conflicts,conflictsRestarts,nbstopsrestarts,nbstopsrestartssame,lastblockatrestart; uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals; +public: + bool gctsGeometric=false, gctsSymmetry=false; + uint64_t geometricOrbitPatterns=0; + uint64_t geometricChecks=0, geometricUnits=0, geometricConflicts=0, geometricTouches=0; protected: + struct AnchorSection {CRef reason;std::vector roles;int zeros=0;bool active=true,queued=false;}; + std::vector anchorSections; + std::vector> anchorIncidence; + std::unordered_map anchorByReason; + std::vector anchorQueue;size_t anchorHead=0; + void anchorAttach(CRef); + void anchorOrbit(const vec&, unsigned int); + void anchorDetach(CRef); + void anchorChange(int,int); + CRef anchorPropagate(); + void anchorRelocate(ClauseAllocator&); long curRestart; // Helper structures: // @@ -276,7 +294,7 @@ // int64_t conflict_budget; // -1 means no budget. int64_t propagation_budget; // -1 means no budget. - bool asynch_interrupt; + std::atomic asynch_interrupt; // Variables added for incremental mode --- solvers/glucose30/core/Solver.cc +++ solvers/glucose30/core/Solver.cc @@ -35,6 +35,13 @@ #include "glucose30/utils/System.h" extern void gcts_trace(int, int, int); +extern void gcts_learn(const Glucose30::vec&); +extern int gcts_anchor_candidate(int); +extern int gcts_symmetry_candidate(int,int); +extern void gcts_orbit_record(const Glucose30::vec&); +#include +#include +#include using namespace Glucose30; #pragma GCC diagnostic ignored "-Wsign-compare" @@ -273,6 +280,7 @@ void Solver::attachClause(CRef cr) { const Clause& c = ca[cr]; + if(gctsGeometric&&c.learnt()){anchorAttach(cr);learnts_literals+=c.size();return;} assert(c.size() > 1); if(c.size()==2) { @@ -290,6 +298,7 @@ void Solver::detachClause(CRef cr, bool strict) { const Clause& c = ca[cr]; + if(gctsGeometric&&c.learnt()){anchorDetach(cr);learnts_literals-=c.size();return;} assert(c.size() > 1); if(c.size()==2) { @@ -319,7 +328,7 @@ Clause& c = ca[cr]; - if (certifiedUNSAT) { + if (certifiedUNSAT && !gctsSymmetry) { fprintf(certifiedOutput, "d "); for (int i = 0; i < c.size(); i++) fprintf(certifiedOutput, "%i ", var(c[i]) * (-2 * sign(c[i]) + 1)); @@ -458,6 +467,7 @@ for (int c = trail.size()-1; c >= trail_lim[level]; c--){ Var x = var(trail[c]); if (x > 0 && x <= 8140 && !sign(trail[c])) gcts_trace(2, x, level); + if(gctsGeometric&&!sign(trail[c]))anchorChange(x,-1); assigns [x] = g3l_Undef; if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) polarity[x] = sign(trail[c]); @@ -492,7 +502,7 @@ }else next = order_heap.removeMin(); - return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]); + return next == var_Undef ? lit_Undef : mkLit(next, false); } @@ -515,176 +525,29 @@ |________________________________________________________________________________________________@*/ void Solver::analyze(CRef confl, vec& out_learnt,vec&selectors, int& out_btlevel,unsigned int &lbd,unsigned int &szWithoutSelectors) { - int pathC = 0; - Lit p = lit_Undef; - - // Generate conflict clause: - // - out_learnt.push(); // (leave room for the asserting literal) - int index = trail.size() - 1; - - do{ - assert(confl != CRef_Undef); // (otherwise should be UIP) - Clause& c = ca[confl]; - - // Special case for binary clauses - // The first one has to be SAT - if( p != lit_Undef && c.size()==2 && value(c[0])==g3l_False) { - - assert(value(c[1])==g3l_True); - Lit tmp = c[0]; - c[0] = c[1], c[1] = tmp; - } - - if (c.learnt()) - claBumpActivity(c); - -#ifdef DYNAMICNBLEVEL - // DYNAMIC NBLEVEL trick (see competition'09 companion paper) - if(c.learnt() && c.lbd()>2) { - unsigned int nblevels = computeLBD(c); - if(nblevels+1 0){ - if(!isSelector(var(q))) - varBumpActivity(var(q)); - seen[var(q)] = 1; - if (level(var(q)) >= decisionLevel()) { - pathC++; -#ifdef UPDATEVARACTIVITY - // UPDATEVARACTIVITY trick (see competition'09 companion paper) - if(!isSelector(var(q)) && (reason(var(q))!= CRef_Undef) && ca[reason(var(q))].learnt()) - lastDecisionLevel.push(q); -#endif - - } else { - if(isSelector(var(q))) { - assert(value(q) == g3l_False); - selectors.push(q); - } else - out_learnt.push(q); - } - } - } - - // Select next clause to look at: - while (!seen[var(trail[index--])]); - p = trail[index+1]; - confl = reason(var(p)); - seen[var(p)] = 0; - pathC--; - - }while (pathC > 0); - out_learnt[0] = ~p; - - // Simplify conflict clause: - // - int i, j; - - for(int i = 0;i 0){ - out_learnt[j++] = out_learnt[i]; - break; } - } - } - }else - i = j = out_learnt.size(); - - max_literals += out_learnt.size(); - out_learnt.shrink(i - j); - tot_literals += out_learnt.size(); - - - /* *************************************** - Minimisation with binary clauses of the asserting clause - First of all : we look for small clauses - Then, we reduce clauses with small LBD. - Otherwise, this can be useless - */ - if(!incremental && out_learnt.size()<=lbSizeMinimizingClause) { - minimisationWithBinaryResolution(out_learnt); - } - // Find correct backtrack level: - // - if (out_learnt.size() == 1) - out_btlevel = 0; - else{ - int max_i = 1; - // Find the first literal assigned at the next-highest level: - for (int i = 2; i < out_learnt.size(); i++) - if (level(var(out_learnt[i])) > level(var(out_learnt[max_i]))) - max_i = i; - // Swap-in this literal at index 1: - Lit p = out_learnt[max_i]; - out_learnt[max_i] = out_learnt[1]; - out_learnt[1] = p; - out_btlevel = level(var(p)); - } - - - // Compute the size of the clause without selectors (incremental mode) - if(incremental) { - szWithoutSelectors = 0; - for(int i=0;i0) break; + std::vector cut(nVars(),0); + int current=0; + auto add=[&](Lit q){Var v=var(q);if(level(v)==0)return;if(!cut[v]){cut[v]=sign(q)?-1:1;if(level(v)==decisionLevel())current++;varBumpActivity(v);}else if(cut[v]!=(sign(q)?-1:1))std::abort();}; + for(int j=0;j=0;pos--){Var v=var(trail[pos]);if(!cut[v])continue; + if(cut[v]>0 || (level(v)==decisionLevel()&¤t>1)){ + CRef r=reason(v);if(r==CRef_Undef)std::abort(); + if(level(v)==decisionLevel())current--;cut[v]=0; + Clause& c=ca[r];if(c.learnt())claBumpActivity(c); + for(int j=0;j0) { - for(int i = 0;i0)std::abort();out_learnt.push(mkLit(v,true));} + if(!out_learnt.size())std::abort(); + int highest=0;for(int j=1;jlevel(var(out_learnt[highest])))highest=j; + Lit temp=out_learnt[0];out_learnt[0]=out_learnt[highest];out_learnt[highest]=temp; + out_btlevel=0;if(out_learnt.size()>1){int second=1;for(int j=2;jlevel(var(out_learnt[second])))second=j;temp=out_learnt[1];out_learnt[1]=out_learnt[second];out_learnt[second]=temp;out_btlevel=level(var(out_learnt[1]));} + if(out_btlevel>=level(var(out_learnt[0])))std::abort(); + szWithoutSelectors=out_learnt.size();lbd=computeLBD(out_learnt,out_learnt.size()); + max_literals+=out_learnt.size();tot_literals+=out_learnt.size(); + gcts_learn(out_learnt); } @@ -773,6 +636,7 @@ assigns[var(p)] = lbool(!sign(p)); vardata[var(p)] = mkVarData(from, decisionLevel()); trail.push_(p); + if(gctsGeometric&&!sign(p))anchorChange(var(p),1); if (var(p) > 0 && var(p) <= 8140 && !sign(p)) gcts_trace(1, var(p), decisionLevel()); } @@ -846,7 +710,9 @@ int num_props = 0; watches.cleanAll(); watchesBin.cleanAll(); - while (qhead < trail.size()){ + while (qhead < trail.size() || (gctsGeometric&&anchorHead=trail.size()){confl=anchorPropagate();continue;} Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. vec& ws = watches[p]; Watcher *i, *j, *end; @@ -1100,6 +966,7 @@ starts++; gcts_trace(6, starts, decisionLevel()); for (;;){ + if(!withinBudget())return g3l_Undef; CRef confl = propagate(); if (confl != CRef_Undef){ // CONFLICT @@ -1158,6 +1025,7 @@ claBumpActivity(ca[cr]); uncheckedEnqueue(learnt_clause[0], cr); } + if(gctsSymmetry)anchorOrbit(learnt_clause,nblevels); varDecayActivity(); claDecayActivity(); @@ -1623,6 +1491,7 @@ void Solver::relocAll(ClauseAllocator& to) { + if(gctsGeometric)anchorRelocate(to); // All watchers: // // for (int i = 0; i < watches.size(); i++) @@ -1673,3 +1542,37 @@ ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } + +void Solver::anchorAttach(CRef cr){ + if(anchorIncidence.size()<(size_t)nVars())anchorIncidence.resize(nVars()); + AnchorSection s;s.reason=cr;Clause& c=ca[cr];int index=anchorSections.size(); + for(int i=0;i=(int)s.roles.size()-1){s.queued=true;anchorQueue.push_back(index);}anchorByReason[cr]=index;anchorSections.push_back(std::move(s)); +} +void Solver::anchorDetach(CRef cr){auto it=anchorByReason.find(cr);if(it==anchorByReason.end())std::abort();auto& s=anchorSections[it->second];s.active=false;std::vector().swap(s.roles);anchorByReason.erase(it);} +void Solver::anchorChange(int v,int delta){ + if((size_t)v>=anchorIncidence.size())return; + for(int index:anchorIncidence[v]){auto& s=anchorSections[index];if(!s.active)continue;geometricTouches++;s.zeros+=delta;if(s.zeros<0||s.zeros>(int)s.roles.size())std::abort();if(s.zeros>=(int)s.roles.size()-1&&!s.queued){s.queued=true;anchorQueue.push_back(index);}} +} +CRef Solver::anchorPropagate(){ + while(anchorHead& source,unsigned int lbd){ + std::set> emitted;std::vector original;for(int i=0;i members;for(int v:original)members.push_back(gcts_symmetry_candidate(v,g));std::sort(members.begin(),members.end());if(!emitted.insert(members).second)continue; + vec image;for(int v:members)image.push(mkLit(v,true)); + if(certifiedUNSAT){for(int v:members)fprintf(certifiedOutput,"%d ",-v);fprintf(certifiedOutput,"0\n");}gcts_orbit_record(image);geometricOrbitPatterns++; + CRef cr=ca.alloc(image,true);ca[cr].setLBD(lbd);ca[cr].setSizeWithoutSelectors(image.size());learnts.push(cr);anchorAttach(cr);learnts_literals+=image.size();claBumpActivity(ca[cr]); + } +}