void solver_reducedb(solver* s) { int i, j; double extra_lim = s->cla_inc / vecp_size(&s->learnts); /* Remove any clause below this activity */ clause** learnts = (clause**)vecp_begin(&s->learnts); clause** reasons = s->reasons; sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), clause_cmp); for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i]) clause_remove(s,learnts[i]); else learnts[j++] = learnts[i]; } for (; i < vecp_size(&s->learnts); i++){ if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i] && clause_activity(learnts[i]) < extra_lim) clause_remove(s,learnts[i]); else learnts[j++] = learnts[i]; } /* printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); */ vecp_resize(&s->learnts,j); }
static inline void solver_canceluntil(solver* s, int level) { lit* trail; lbool* values; clause** reasons; int bound; int c; if (solver_dlevel(s) <= level) return; trail = s->trail; values = s->assigns; reasons = s->reasons; bound = (veci_begin(&s->trail_lim))[level]; for (c = s->qtail-1; c >= bound; c--) { int x = lit_var(trail[c]); values [x] = l_Undef; reasons[x] = (clause*)0; } for (c = s->qhead-1; c >= bound; c--) order_unassigned(s,lit_var(trail[c])); s->qhead = s->qtail = bound; veci_resize(&s->trail_lim,level); }
/**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Pr_Cls_t * Pr_ManPropagateOne( Pr_Man_t * p, lit Lit ) { Pr_Cls_t ** ppPrev, * pCur, * pTemp; lit LitF = lit_neg(Lit); int i; // iterate through the literals ppPrev = p->pWatches + Lit; for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) { // make sure the false literal is in the second literal of the clause if ( pCur->pLits[0] == LitF ) { pCur->pLits[0] = pCur->pLits[1]; pCur->pLits[1] = LitF; pTemp = pCur->pNext0; pCur->pNext0 = pCur->pNext1; pCur->pNext1 = pTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) { ppPrev = &pCur->pNext1; continue; } // look for a new literal to watch for ( i = 2; i < (int)pCur->nLits; i++ ) { // skip the case when the literal is false if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) continue; // the literal is either true or unassigned - watch it pCur->pLits[1] = pCur->pLits[i]; pCur->pLits[i] = LitF; // remove this clause from the watch list of Lit *ppPrev = pCur->pNext1; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Pr_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication if ( Pr_ManEnqueue(p, pCur->pLits[0], pCur) ) { ppPrev = &pCur->pNext1; continue; } // conflict detected - return the conflict clause return pCur; } return NULL; }
/**Function************************************************************* Synopsis [Lifts the clause to depend on NS variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv ) { int iLit, i; Vec_IntClear( vRemapped ); Vec_IntForEachEntry( vClause, iLit, i ) { assert( pMap[lit_var(iLit)] >= 0 ); iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv ); Vec_IntPush( vRemapped, iLit ); }
bool solver_addclause(solver* s, lit* begin, lit* end) { lit *i,*j; int maxvar; lbool* values; lit last; if (begin == end) return false; /* printlits(begin,end); printf("\n"); */ /* insertion sort */ maxvar = lit_var(*begin); for (i = begin + 1; i < end; i++){ lit l = *i; maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; for (j = i; j > begin && *(j-1) > l; j--) *j = *(j-1); *j = l; } solver_setnvars(s,maxvar+1); /* printlits(begin,end); printf("\n"); */ values = s->assigns; /* delete duplicates */ last = lit_Undef; for (i = j = begin; i < end; i++){ /* printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); */ lbool sig = !lit_sign(*i); sig += sig - 1; if (*i == lit_neg(last) || sig == values[lit_var(*i)]) return true; /* tautology */ else if (*i != last && values[lit_var(*i)] == l_Undef) last = *j++ = *i; } /* printf("final: "); printlits(begin,j); printf("\n"); */ if (j == begin) /* empty clause */ return false; else if (j - begin == 1) /* unit clause */ return enqueue(s,*begin,(clause*)0); /* create new clause */ vecp_push(&s->clauses,clause_new(s,begin,j,0)); s->stats.clauses++; s->stats.clauses_literals += j - begin; return true; }
static inline bool enqueue(solver* s, lit l, clause* from) { lbool* values = s->assigns; int v = lit_var(l); lbool val = values[v]; lbool sig; #ifdef VERBOSEDEBUG printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); #endif /* lbool */ sig = !lit_sign(l); sig += sig - 1; if (val != l_Undef){ return val == sig; }else{ /* New fact -- store it. */ int* levels; clause** reasons; #ifdef VERBOSEDEBUG printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); #endif /* int* */ levels = s->levels; /* clause** */ reasons = s->reasons; values [v] = sig; levels [v] = solver_dlevel(s); reasons[v] = from; s->trail[s->qtail++] = l; order_assigned(s, v); return true; } }
static inline void assume(solver* s, lit l){ assert(s->qtail == s->qhead); assert(s->assigns[lit_var(l)] == l_Undef); #ifdef VERBOSEDEBUG printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); #endif veci_push(&s->trail_lim,s->qtail); enqueue(s,l,(clause*)0); }
/**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pr_ManEnqueue( Pr_Man_t * p, lit Lit, Pr_Cls_t * pReason ) { int Var = lit_var(Lit); if ( p->pAssigns[Var] != LIT_UNDEF ) return p->pAssigns[Var] == Lit; p->pAssigns[Var] = Lit; p->pReasons[Var] = pReason; p->pTrail[p->nTrailSize++] = Lit; //printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); return 1; }
/**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Pr_ManCancelUntil( Pr_Man_t * p, int Level ) { lit Lit; int i, Var; for ( i = p->nTrailSize - 1; i >= Level; i-- ) { Lit = p->pTrail[i]; Var = lit_var( Lit ); p->pReasons[Var] = NULL; p->pAssigns[Var] = LIT_UNDEF; //printf( "cancelling var %d\n", Var ); } p->nTrailSize = Level; }
extern "C" value C_create_lit(value v, value solver_In,value sign_In) { CAMLparam3(v, solver_In,sign_In); solver_c s = (solver_c) Field(solver_In, 0); int var_id = Int_val(v); // printf("minisat_ocaml_wrapper: new lit var id: %i\n",var_id); //assume true == True, false == False int sign = Bool_val(sign_In); addVar (s,var_id); lit_c lit = lit_var (var_id, sign); value val = alloc(1, Abstract_tag); Field(val,0) = (value) lit; CAMLreturn(val); }
bool solver_addclause(solver* s, lit* begin, lit* end) { lit *i,*j; int maxvar; if (begin == end) return false; // Empty clause // insertion sort maxvar = lit_var(*begin); for (i = begin + 1; i < end; i++){ lit l = *i; maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; for (j = i; j > begin && *(j-1) > l; j--) *j = *(j-1); *j = l; } solver_setnvars(s,maxvar+1); // create new clause vecp_push(&s->clauses,clause_new(s,begin,end)); s->tail++; // tail == # of clauses at first. return true; }
static lbool clause_simplify(solver* s, clause* c) { lit* lits = clause_begin(c); lbool* values = s->assigns; int i; assert(solver_dlevel(s) == 0); for (i = 0; i < clause_size(c); i++){ lbool sig = !lit_sign(lits[i]); sig += sig - 1; if (values[lit_var(lits[i])] == sig) return l_True; } return l_False; }
bool solver_simplify(solver* s) { clause** reasons; int type; assert(solver_dlevel(s) == 0); if (solver_propagate(s) != 0) return false; if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) return true; reasons = s->reasons; for (type = 0; type < 2; type++){ vecp* cs = type ? &s->learnts : &s->clauses; clause** cls = (clause**)vecp_begin(cs); int i, j; for (j = i = 0; i < vecp_size(cs); i++){ if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && clause_simplify(s,cls[i]) == l_True) clause_remove(s,cls[i]); else cls[j++] = cls[i]; } vecp_resize(cs,j); } s->simpdb_assigns = s->qhead; /* (shouldn't depend on 'stats' really, but it will do for now) */ s->simpdb_props = (int)(s->stats.clauses_literals + s->stats.learnts_literals); return true; }
/**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pr_ManProofTraceOne( Pr_Man_t * p, Pr_Cls_t * pConflict, Pr_Cls_t * pFinal ) { Pr_Cls_t * pReason; int i, v, Var, PrevId; int fPrint = 0; int clk = clock(); // collect resolvent literals if ( p->fProofVerif ) { assert( (int)pConflict->nLits <= p->nResLitsAlloc ); memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); p->nResLits = pConflict->nLits; } // mark all the variables in the conflict as seen for ( v = 0; v < (int)pConflict->nLits; v++ ) p->pSeens[lit_var(pConflict->pLits[v])] = 1; // start the anticedents // pFinal->pAntis = Vec_PtrAlloc( 32 ); // Vec_PtrPush( pFinal->pAntis, pConflict ); if ( p->nClausesA ) pFinal->uTruth = pConflict->uTruth; // follow the trail backwards PrevId = (int)pConflict->pProof; for ( i = p->nTrailSize - 1; i >= 0; i-- ) { // skip literals that are not involved Var = lit_var(p->pTrail[i]); if ( !p->pSeens[Var] ) continue; p->pSeens[Var] = 0; // skip literals of the resulting clause pReason = p->pReasons[Var]; if ( pReason == NULL ) continue; assert( p->pTrail[i] == pReason->pLits[0] ); // add the variables to seen for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; // record the reason clause assert( pReason->pProof > 0 ); p->Counter++; if ( p->fProofWrite ) fprintf( p->pManProof, "%d * %d %d 0\n", p->Counter, PrevId, (int)pReason->pProof ); PrevId = p->Counter; if ( p->nClausesA ) { if ( p->pVarTypes[Var] == 1 ) // var of A pFinal->uTruth |= pReason->uTruth; else pFinal->uTruth &= pReason->uTruth; } // resolve the temporary resolvent with the reason clause if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Pr_ManPrintResolvent( p->pResLits, p->nResLits ); // check that the var is present in the resolvent for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == Var ) break; if ( v1 == p->nResLits ) printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); // remove this variable from the resolvent assert( lit_var(p->pResLits[v1]) == Var ); p->nResLits--; for ( ; v1 < p->nResLits; v1++ ) p->pResLits[v1] = p->pResLits[v1+1]; // add variables of the reason clause for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) { for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) break; // if it is a new variable, add it to the resolvent if ( v1 == p->nResLits ) { if ( p->nResLits == p->nResLitsAlloc ) printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" ); p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; continue; } // if the variable is the same, the literal should be the same too if ( p->pResLits[v1] == pReason->pLits[v2] ) continue; // the literal is different printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); } } // Vec_PtrPush( pFinal->pAntis, pReason ); } // unmark all seen variables // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // p->pSeens[lit_var(p->pTrail[i])] = 0; // check that the literals are unmarked // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); // use the resulting clause to check the correctness of resolution if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Pr_ManPrintResolvent( p->pResLits, p->nResLits ); for ( v1 = 0; v1 < p->nResLits; v1++ ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) if ( pFinal->pLits[v2] == p->pResLits[v1] ) break; if ( v2 < (int)pFinal->nLits ) continue; break; } if ( v1 < p->nResLits ) { printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); Pr_ManPrintClause( pConflict ); Pr_ManPrintResolvent( p->pResLits, p->nResLits ); Pr_ManPrintClause( pFinal ); } } p->timeTrace += clock() - clk; // return the proof pointer if ( p->nClausesA ) { Pr_ManPrintInterOne( p, pFinal ); } return p->Counter; }
bool solver_solve(solver* s, lit* begin, lit* end) { double nof_conflicts = 100; double nof_learnts = solver_nclauses(s) / 3; lbool status = l_Undef; lbool* values = s->assigns; lit* i; /* printf("solve: "); printlits(begin, end); printf("\n"); */ for (i = begin; i < end; i++){ switch (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]){ case 1: /* l_True: */ break; case 0: /* l_Undef */ assume(s, *i); if (solver_propagate(s) == NULL) break; /* falltrough */ case -1: /* l_False */ solver_canceluntil(s, 0); return false; } } s->root_level = solver_dlevel(s); if (s->verbosity >= 1){ printf("==================================[MINISAT]============" "=======================\n"); printf("| Conflicts | ORIGINAL | LEARNT " " | Progress |\n"); printf("| | Clauses Literals | Limit Clauses Litera" "ls Lit/Cl | |\n"); printf("=======================================================" "=======================\n"); } while (status == l_Undef){ double Ratio = (s->stats.learnts == 0)? 0.0 : s->stats.learnts_literals / (double)s->stats.learnts; if (s->verbosity >= 1){ printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %" "6.3f %% |\n", (double)s->stats.conflicts, (double)s->stats.clauses, (double)s->stats.clauses_literals, (double)nof_learnts, (double)s->stats.learnts, (double)s->stats.learnts_literals, Ratio, s->progress_estimate*100); fflush(stdout); } status = solver_search(s,(int)nof_conflicts, (int)nof_learnts); nof_conflicts *= 1.5; nof_learnts *= 1.1; } if (s->verbosity >= 1) printf("=======================================================" "=======================\n"); solver_canceluntil(s,0); return status != l_False; }
/**Function************************************************************* Synopsis [Adds one clause to the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA ) { Pr_Cls_t * pClause; lit Lit, * i, * j; int nSize, VarMax; // process the literals if ( pBeg < pEnd ) { // insertion sort VarMax = lit_var( *pBeg ); for ( i = pBeg + 1; i < pEnd; i++ ) { Lit = *i; VarMax = lit_var(Lit) > VarMax ? lit_var(Lit) : VarMax; for ( j = i; j > pBeg && *(j-1) > Lit; j-- ) *j = *(j-1); *j = Lit; } // make sure there is no duplicated variables for ( i = pBeg + 1; i < pEnd; i++ ) assert( lit_var(*(i-1)) != lit_var(*i) ); // resize the manager Pr_ManResize( p, VarMax+1 ); } // get memory for the clause nSize = sizeof(Pr_Cls_t) + sizeof(lit) * (pEnd - pBeg); pClause = (Pr_Cls_t *)Pr_ManMemoryFetch( p, nSize ); memset( pClause, 0, sizeof(Pr_Cls_t) ); // assign the clause assert( !fClauseA || fRoot ); // clause of A is always a root clause p->nRoots += fRoot; p->nClausesA += fClauseA; pClause->Id = p->nClauses++; pClause->fA = fClauseA; pClause->fRoot = fRoot; pClause->nLits = pEnd - pBeg; memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) ); // add the clause to the list if ( p->pHead == NULL ) p->pHead = pClause; if ( p->pTail == NULL ) p->pTail = pClause; else { p->pTail->pNext = pClause; p->pTail = pClause; } // mark the first learnt clause if ( p->pLearnt == NULL && !pClause->fRoot ) p->pLearnt = pClause; // add the empty clause if ( pClause->nLits == 0 ) { if ( p->pEmpty ) printf( "More than one empty clause!\n" ); p->pEmpty = pClause; } return 1; }
static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; }
int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int Level, int Pol ) { Vec_Int_t * vLits; sat_solver * pSat; Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k); int nVarCount = Vec_IntSize(vVar2Ids); int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj ); int * pLit, i, iVar, iClaBeg, iClaEnd, RetValue; int PolPres = (iVarThis & 3); iVarThis >>= 2; if ( Aig_ObjIsCi(pObj) ) return iVarThis; // Pol = 3; // if ( nVarCount != Vec_IntSize(vVar2Ids) || (Pol & ~PolPres) ) if ( (Pol & ~PolPres) ) { *Vec_IntEntryP( p->pvId2Vars + Aig_ObjId(pObj), k ) |= Pol; iClaBeg = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)]; iClaEnd = iClaBeg + p->pCnf2->pObj2Count[Aig_ObjId(pObj)]; assert( iClaBeg < iClaEnd ); /* if ( (Pol & ~PolPres) != 3 ) for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) { printf( "Clause %5d : ", i ); for ( iVar = 0; iVar < 4; iVar++ ) printf( "%d ", ((unsigned)p->pCnf2->pClaPols[i] >> (2*iVar)) & 3 ); printf( " " ); for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) printf( "%6d ", *pLit ); printf( "\n" ); } */ pSat = Pdr_ManSolver(p, k); vLits = Vec_WecEntry( p->vVLits, Level ); if ( (Pol & ~PolPres) == 3 ) { assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) ); for ( i = iClaBeg; i < iClaEnd; i++ ) { Vec_IntClear( vLits ); Vec_IntPush( vLits, toLitCond( iVarThis, lit_sign(p->pCnf2->pClauses[i][0]) ) ); for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) { iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, 3 ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( RetValue ); (void) RetValue; } } else // if ( (Pol & ~PolPres) == 2 || (Pol & ~PolPres) == 1 ) // write pos/neg polarity { assert( (Pol & ~PolPres) ); for ( i = iClaBeg; i < iClaEnd; i++ ) if ( 2 - !Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) == (Pol & ~PolPres) ) // taking opposite literal { Vec_IntClear( vLits ); Vec_IntPush( vLits, toLitCond( iVarThis, Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) ) ); for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) { iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, ((unsigned)p->pCnf2->pClaPols[i] >> (2*(pLit-p->pCnf2->pClauses[i]-1))) & 3 ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( RetValue ); (void) RetValue; } }
clause* solver_propagate(solver* s) { lbool* values = s->assigns; clause* confl = (clause*)0; lit* lits; /* printf("solver_propagate\n"); */ while (confl == 0 && s->qtail - s->qhead > 0){ lit p = s->trail[s->qhead++]; vecp* ws = solver_read_wlist(s,p); clause **begin = (clause**)vecp_begin(ws); clause **end = begin + vecp_size(ws); clause **i, **j; s->stats.propagations++; s->simpdb_props--; /* printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p)); */ for (i = j = begin; i < end; ){ if (clause_is_lit(*i)){ *j++ = *i; if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ confl = s->binary; (clause_begin(confl))[1] = lit_neg(p); (clause_begin(confl))[0] = clause_read_lit(*i++); /* Copy the remaining watches: */ while (i < end) *j++ = *i++; } }else{ lit false_lit; lbool sig; lits = clause_begin(*i); /* Make sure the false literal is data[1]: */ false_lit = lit_neg(p); if (lits[0] == false_lit){ lits[0] = lits[1]; lits[1] = false_lit; } assert(lits[1] == false_lit); /* printf("checking clause: "); printlits(lits, lits+clause_size(*i)); printf("\n"); */ /* If 0th watch is true, then clause is already satisfied. */ sig = !lit_sign(lits[0]); sig += sig - 1; if (values[lit_var(lits[0])] == sig){ *j++ = *i; }else{ /* Look for new watch: */ lit* stop = lits + clause_size(*i); lit* k; for (k = lits + 2; k < stop; k++){ lbool sig = lit_sign(*k); sig += sig - 1; if (values[lit_var(*k)] != sig){ lits[1] = *k; *k = false_lit; vecp_push(solver_read_wlist(s, lit_neg(lits[1])),*i); goto next; } } *j++ = *i; /* Clause is unit under assignment: */ if (!enqueue(s,lits[0], *i)){ confl = *i++; /* Copy the remaining watches: */ while (i < end) *j++ = *i++; } } } next: i++; } s->stats.inspects += j - (clause**)vecp_begin(ws); vecp_resize(ws,j - (clause**)vecp_begin(ws)); } return confl; }
static void solver_analyze(solver* s, clause* c, veci* learnt) { lit* trail = s->trail; lbool* tags = s->tags; clause** reasons = s->reasons; int* levels = s->levels; int cnt = 0; lit p = lit_Undef; int ind = s->qtail-1; lit* lits; int i, j, minl; int* tagged; veci_push(learnt,lit_Undef); do{ assert(c != 0); if (clause_is_lit(c)){ lit q = clause_read_lit(c); assert(lit_var(q) >= 0 && lit_var(q) < s->size); if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ tags[lit_var(q)] = l_True; veci_push(&s->tagged,lit_var(q)); act_var_bump(s,lit_var(q)); if (levels[lit_var(q)] == solver_dlevel(s)) cnt++; else veci_push(learnt,q); } }else{ if (clause_learnt(c)) act_clause_bump(s,c); lits = clause_begin(c); /* printlits(lits,lits+clause_size(c)); printf("\n"); */ for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ lit q = lits[j]; assert(lit_var(q) >= 0 && lit_var(q) < s->size); if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ tags[lit_var(q)] = l_True; veci_push(&s->tagged,lit_var(q)); act_var_bump(s,lit_var(q)); if (levels[lit_var(q)] == solver_dlevel(s)) cnt++; else veci_push(learnt,q); } } } while (tags[lit_var(trail[ind--])] == l_Undef); p = trail[ind+1]; c = reasons[lit_var(p)]; cnt--; }while (cnt > 0); *veci_begin(learnt) = lit_neg(p); lits = veci_begin(learnt); minl = 0; for (i = 1; i < veci_size(learnt); i++){ int lev = levels[lit_var(lits[i])]; minl |= 1 << (lev & 31); } /* simplify (full) */ for (i = j = 1; i < veci_size(learnt); i++){ if (reasons[lit_var(lits[i])] == 0 || !solver_lit_removable(s,lits[i],minl)) lits[j++] = lits[i]; } /* update size of learnt + statistics */ s->stats.max_literals += veci_size(learnt); veci_resize(learnt,j); s->stats.tot_literals += j; /* clear tags */ tagged = veci_begin(&s->tagged); for (i = 0; i < veci_size(&s->tagged); i++) tags[tagged[i]] = l_Undef; veci_resize(&s->tagged,0); #ifdef DEBUG for (i = 0; i < s->size; i++) assert(tags[i] == l_Undef); #endif #ifdef VERBOSEDEBUG printf(L_IND"Learnt {", L_ind); for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); #endif if (veci_size(learnt) > 1){ int max_i = 1; int max = levels[lit_var(lits[1])]; lit tmp; for (i = 2; i < veci_size(learnt); i++) if (levels[lit_var(lits[i])] > max){ max = levels[lit_var(lits[i])]; max_i = i; } tmp = lits[1]; lits[1] = lits[max_i]; lits[max_i] = tmp; } #ifdef VERBOSEDEBUG { int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; printf(" } at level %d\n", lev); } #endif }
static bool solver_lit_removable(solver* s, lit l, int minl) { lbool* tags = s->tags; clause** reasons = s->reasons; int* levels = s->levels; int top = veci_size(&s->tagged); assert(lit_var(l) >= 0 && lit_var(l) < s->size); assert(reasons[lit_var(l)] != 0); veci_resize(&s->stack,0); veci_push(&s->stack,lit_var(l)); while (veci_size(&s->stack) > 0){ clause* c; int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; assert(v >= 0 && v < s->size); veci_resize(&s->stack,veci_size(&s->stack)-1); assert(reasons[v] != 0); c = reasons[v]; if (clause_is_lit(c)){ int v = lit_var(clause_read_lit(c)); if (tags[v] == l_Undef && levels[v] != 0){ if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ veci_push(&s->stack,v); tags[v] = l_True; veci_push(&s->tagged,v); }else{ int* tagged = veci_begin(&s->tagged); int j; for (j = top; j < veci_size(&s->tagged); j++) tags[tagged[j]] = l_Undef; veci_resize(&s->tagged,top); return false; } } }else{ lit* lits = clause_begin(c); int i, j; for (i = 1; i < clause_size(c); i++){ int v = lit_var(lits[i]); if (tags[v] == l_Undef && levels[v] != 0){ if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ veci_push(&s->stack,lit_var(lits[i])); tags[v] = l_True; veci_push(&s->tagged,v); }else{ int* tagged = veci_begin(&s->tagged); for (j = top; j < veci_size(&s->tagged); j++) tags[tagged[j]] = l_Undef; veci_resize(&s->tagged,top); return false; } } } } } return true; }
static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) { int* levels = s->levels; double var_decay = 0.95; double clause_decay = 0.999; double random_var_freq = 0.02; int conflictC = 0; veci learnt_clause; assert(s->root_level == solver_dlevel(s)); s->stats.starts++; s->var_decay = (float)(1 / var_decay ); s->cla_decay = (float)(1 / clause_decay); veci_resize(&s->model,0); veci_new(&learnt_clause); for (;;){ clause* confl = solver_propagate(s); if (confl != 0){ /* CONFLICT */ int blevel; #ifdef VERBOSEDEBUG printf(L_IND"**CONFLICT**\n", L_ind); #endif s->stats.conflicts++; conflictC++; if (solver_dlevel(s) == s->root_level){ veci_delete(&learnt_clause); return l_False; } veci_resize(&learnt_clause,0); solver_analyze(s, confl, &learnt_clause); blevel = veci_size(&learnt_clause) > 1 ? levels[lit_var(veci_begin(&learnt_clause)[1])] : s->root_level; blevel = s->root_level > blevel ? s->root_level : blevel; solver_canceluntil(s,blevel); solver_record(s,&learnt_clause); act_var_decay(s); act_clause_decay(s); }else{ /* NO CONFLICT */ int next; if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ /* Reached bound on number of conflicts: */ s->progress_estimate = solver_progress(s); solver_canceluntil(s,s->root_level); veci_delete(&learnt_clause); return l_Undef; } if (solver_dlevel(s) == 0) /* Simplify the set of problem clauses: */ solver_simplify(s); if (nof_learnts >= 0 && vecp_size(&s->learnts) - s->qtail >= nof_learnts) /* Reduce the set of learnt clauses: */ solver_reducedb(s); /* New variable decision: */ s->stats.decisions++; next = order_select(s,(float)random_var_freq); if (next == var_Undef){ /* Model found: */ lbool* values = s->assigns; int i; for (i = 0; i < s->size; i++) veci_push(&s->model,(int)values[i]); solver_canceluntil(s,s->root_level); veci_delete(&learnt_clause); /* veci apa; veci_new(&apa); for (i = 0; i < s->size; i++) veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i)))); printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n"); veci_delete(&apa); */ return l_True; } assume(s,lit_neg(toLit(next))); } } #if 0 /* by mao; unreachable code */ return l_Undef; /* cannot happen */ #endif }
static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; }