void resolve(vec<Lit>& main, vec<Lit>& other, Var x) { Lit p; bool ok1 = false, ok2 = false; for (int i = 0; i < main.size(); i++){ if (var(main[i]) == x){ ok1 = true, p = main[i]; main[i] = main.last(); main.pop(); break; } } for (int i = 0; i < other.size(); i++){ if (var(other[i]) != x) main.push(other[i]); else{ if (p != ~other[i]) printf("PROOF ERROR! Resolved on variable with SAME polarity in both clauses: %d\n", x+1); ok2 = true; } } if (!ok1 || !ok2) printf("PROOF ERROR! Resolved on missing variable: %d\n", x+1); sortUnique(main); }
ClauseId Proof::addRoot(vec<Lit>& cl) { cl.copyTo(clause); sortUnique(clause); if (trav != NULL) trav->root(clause); if (!fp.null()){ putUInt(fp, index(clause[0]) << 1); for (int i = 1; i < clause.size(); i++) putUInt(fp, index(clause[i]) - index(clause[i-1])); putUInt(fp, 0); // (0 is safe terminator since we removed duplicates) } return id_counter++; }
/*_________________________________________________________________________________________________ | | newClause : (ps : const vec<Lit>&) (learnt : bool) -> [void] | | Description: | Allocate and add a new clause to the SAT solvers clause database. If a conflict is detected, | the 'ok' flag is cleared and the solver is in an unusable state (must be disposed). | | Input: | ps - The new clause as a vector of literals. | learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the | asserting literal. An appropriate 'enqueue()' operation will be performed on this | literal. One of the watches will always be on this literal, the other will be set to | the literal with the highest decision level. | | Effect: | Activity heuristics are updated. |________________________________________________________________________________________________@*/ void Solver::newClause(const vec<Lit>& ps_, bool learnt) { if (!ok) return; vec<Lit> qs; if (!learnt){ assert(decisionLevel() == 0); ps_.copyTo(qs); // Make a copy of the input vector. // Remove duplicates: sortUnique(qs); // Check if clause is satisfied: for (int i = 0; i < qs.size()-1; i++){ if (qs[i] == ~qs[i+1]) return; } for (int i = 0; i < qs.size(); i++){ if (value(qs[i]) == l_True) return; } // Remove false literals: int i, j; for (i = j = 0; i < qs.size(); i++) if (value(qs[i]) != l_False) qs[j++] = qs[i]; qs.shrink(i - j); } const vec<Lit>& ps = learnt ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals. if (ps.size() == 0){ ok = false; }else if (ps.size() == 1){ // NOTE: If enqueue takes place at root level, the assignment will be lost in incremental use (it doesn't seem to hurt much though). if (!enqueue(ps[0])) ok = false; }else if (ps.size() == 2){ // Create special binary clause watch: watches[index(~ps[0])].push(GClause_new(ps[1])); watches[index(~ps[1])].push(GClause_new(ps[0])); if (learnt){ check(enqueue(ps[0], GClause_new(~ps[1]))); stats.learnts_literals += ps.size(); }else stats.clauses_literals += ps.size(); n_bin_clauses++; }else{ // Allocate clause: Clause* c = Clause_new(learnt, ps); if (learnt){ // Put the second watch on the literal with highest decision level: int max_i = 1; int max = level[var(ps[1])]; for (int i = 2; i < ps.size(); i++) if (level[var(ps[i])] > max) max = level[var(ps[i])], max_i = i; (*c)[1] = ps[max_i]; (*c)[max_i] = ps[1]; // Bump, enqueue, store clause: claBumpActivity(c); // (newly learnt clauses should be considered active) check(enqueue((*c)[0], GClause_new(c))); learnts.push(c); stats.learnts_literals += c->size(); }else{ // Store clause: clauses.push(c); stats.clauses_literals += c->size(); } // Watch clause: watches[index(~(*c)[0])].push(GClause_new(c)); watches[index(~(*c)[1])].push(GClause_new(c)); } }