// 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()){

        // 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++];
            (*bwdsub_tmpunit)[0] = l;
            bwdsub_tmpunit->calcAbstraction();
            assert(bwdsub_tmpunit->mark() == 0);
            subsumption_queue.insert(bwdsub_tmpunit); }

        Clause&  c = *subsumption_queue.peek(); subsumption_queue.pop();

        if (c.mark()) continue;

        if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
            reportf("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<Clause*>& _cs = getOccurs(best);
        Clause**       cs = (Clause**)_cs;

        for (int j = 0; j < _cs.size(); j++)
            if (c.mark())
                break;
            else if (!cs[j]->mark() && cs[j] != &c){
                Lit l = c.subsumes(*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;
}
示例#2
0
bool SimpSMTSolver::eliminateVar(Var v, bool fail)
{
  if (!fail && asymm_mode && !asymmVar(v))    return false;

  const vec<Clause*>& cls = getOccurs(v);

  //  if (value(v) != l_Undef || cls.size() == 0) return true;
  if (value(v) != l_Undef) return true;

  // Split the occurrences into positive and negative:
  vec<Clause*>  pos, neg;
  for (int i = 0; i < cls.size(); i++)
    (find(*cls[i], Lit(v)) ? pos : neg).push(cls[i]);

  // Check if number of clauses decreases:
  int cnt = 0;
  for (int i = 0; i < pos.size(); i++)
    for (int j = 0; j < neg.size(); j++)
      if (merge(*pos[i], *neg[j], v) && ++cnt > cls.size() + grow)
	return true;
#ifdef PEDANTIC_DEBUG
  cerr << "XXY gonna-remove" << endl;
#endif
  // Delete and store old clauses:
  setDecisionVar(v, false);
  elimtable[v].order = elimorder++;
  assert(elimtable[v].eliminated.size() == 0);
  for (int i = 0; i < cls.size(); i++)
  {
    elimtable[v].eliminated.push(Clause_new(*cls[i]));
    removeClause(*cls[i]);
  }

  // Produce clauses in cross product:
  int top = clauses.size();
  vec<Lit> resolvent;
  for (int i = 0; i < pos.size(); i++)
    for (int j = 0; j < neg.size(); j++)
      if (merge(*pos[i], *neg[j], v, resolvent) && !addClause(resolvent))
	return false;

  // DEBUG: For checking that a clause set is saturated with respect to variable elimination.
  //        If the clause set is expected to be saturated at this point, this constitutes an
  //        error.
  if (fail){
    reportf("eliminated var %d, %d <= %d\n", v+1, cnt, cls.size());
    reportf("previous clauses:\n");
    for (int i = 0; i < cls.size(); i++){
      printClause(*cls[i]); reportf("\n"); }
    reportf("new clauses:\n");
    for (int i = top; i < clauses.size(); i++){
      printClause(*clauses[i]); reportf("\n"); }
    assert(0); }

    return backwardSubsumptionCheck();
}
bool SimpSolver::asymmVar(Var v)
{
    assert(!frozen[v]);
    assert(use_simplification);

    vec<Clause*>  pos, neg;
    const vec<Clause*>& cls = getOccurs(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();
}
void SimpSolver::gatherTouchedClauses()
{
    //fprintf(stderr, "Gathering clauses for backwards subsumption\n");
    int ntouched = 0;
    for (int i = 0; i < touched.size(); i++)
        if (touched[i]){
            const vec<Clause*>& cs = getOccurs(i);
            ntouched++;
            for (int j = 0; j < cs.size(); j++)
                if (cs[j]->mark() == 0){
                    subsumption_queue.insert(cs[j]);
                    cs[j]->mark(2);
                }
            touched[i] = 0;
        }

    //fprintf(stderr, "Touched variables %d of %d yields %d clauses to check\n", ntouched, touched.size(), clauses.size());
    for (int i = 0; i < subsumption_queue.size(); i++)
        subsumption_queue[i]->mark(0);
}