Beispiel #1
0
/**
@brief Returns if we already know that var = lit

Also checks if var = ~lit, in which it sets solver.ok = false
*/
bool VarReplacer::alreadyIn(const Var var, const Lit lit)
{
    Lit lit2 = table[var];
    if (lit2.var() == lit.var()) {
        if (lit2.sign() != lit.sign()) {
            #ifdef VERBOSE_DEBUG
            cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
            #endif
            solver.ok = false;
        }
        return true;
    }

    lit2 = table[lit.var()];
    if (lit2.var() == var) {
        if (lit2.sign() != lit.sign()) {
            #ifdef VERBOSE_DEBUG
            cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
            #endif
            solver.ok = false;
        }
        return true;
    }

    return false;
}
void SolutionExtender::replaceBackwardSet(const Lit toSet)
{
    //set backward equiv
    map<uint32_t, vector<uint32_t> >::const_iterator revTable = solver->varReplacer->getReverseTable().find(toSet.var());
    if (revTable != solver->varReplacer->getReverseTable().end()) {
        const vector<uint32_t>& toGoThrough = revTable->second;
        for (size_t i = 0; i < toGoThrough.size(); i++) {
            //Get sign of replacement
            const Lit lit = Lit(toGoThrough[i], false);
            Lit tmp = solver->varReplacer->get_lit_replaced_with(lit);

            //Set var
            enqueue(lit ^ tmp.sign() ^ toSet.sign());
        }
    }
}
void SolutionExtender::addClause(const vector<Lit>& lits, const Lit blockedOn)
{
    const uint32_t blocked_on_inter = solver->map_outer_to_inter(blockedOn.var());
    assert(solver->varData[blocked_on_inter].removed == Removed::elimed);
    assert(contains_lit(lits, blockedOn));
    if (satisfied(lits))
        return;

    #ifdef VERBOSE_DEBUG_SOLUTIONEXTENDER
    for(Lit lit: lits) {
        Lit lit_inter = solver->map_outer_to_inter(lit);
        cout
        << lit << ": " << solver->model_value(lit)
        << "(elim: " << removed_type_to_string(solver->varData[lit_inter.var()].removed) << ")"
        << ", ";
    }
    cout << "blocked on: " <<  blockedOn << endl;
    #endif

    if (solver->model_value(blockedOn) != l_Undef) {
        cout << "ERROR: Model value for var " << blockedOn.unsign() << " is "
        << solver->model_value(blockedOn) << " but that doesn't satisfy a v-elim clause on the stack!"
        << endl;
    }
    assert(solver->model_value(blockedOn) == l_Undef);
    solver->model[blockedOn.var()] = blockedOn.sign() ? l_False : l_True;
    if (solver->conf.verbosity >= 10) {
        cout << "Extending VELIM cls. -- setting model for var "
        << blockedOn.unsign() << " to " << solver->model[blockedOn.var()] << endl;
    }

    assert(satisfied(lits));

    solver->varReplacer->extend_model(blockedOn.var());
}
void SolutionExtender::addClause(const vector<Lit>& lits, const Lit blockedOn)
{
    const Var blocked_on_inter = solver->map_outer_to_inter(blockedOn.var());
    assert(solver->varData[blocked_on_inter].removed == Removed::elimed);
    assert(contains_lit(lits, blockedOn));
    if (satisfied(lits))
        return;

    #ifdef VERBOSE_DEBUG_SOLUTIONEXTENDER
    for(Lit lit: lits) {
        Lit lit_inter = solver->map_outer_to_inter(lit);
        cout
        << lit << ": " << solver->model_value(lit)
        << "(elim: " << removed_type_to_string(solver->varData[lit_inter.var()].removed) << ")"
        << ", ";
    }
    cout << "blocked on: " <<  blockedOn << endl;
    #endif

    assert(solver->model_value(blockedOn) == l_Undef);
    solver->model[blockedOn.var()] = blockedOn.sign() ? l_False : l_True;
    assert(satisfied(lits));

    solver->varReplacer->extend_model(blockedOn.var());
}
void CalcDefPolars::tallyVotesBinTri(const vector<vec<Watched> >& watches)
{
    size_t wsLit = 0;
    for (vector<vec<Watched> >::const_iterator
        it = watches.begin(), end = watches.end()
        ; it != end
        ; it++, wsLit++
    ) {
        Lit lit = Lit::toLit(wsLit);
        const vec<Watched>& ws = *it;
        for (vec<Watched>::const_iterator it2 = ws.begin(), end2 = ws.end(); it2 != end2; it2++) {

            //Only count bins once
            if (it2->isBinary()
                && lit < it2->lit2()
                && !it2->learnt()
            ) {

                if (lit.sign()) votes[lit.var()] += 0.5;
                else votes[lit.var()] -= 0.5;

                Lit lit2 = it2->lit2();
                if (lit2.sign()) votes[lit2.var()] += 0.5;
                else votes[lit2.var()] -= 0.5;
            }

            //Only count TRI-s once
            if (it2->isTri()
                && lit < it2->lit2()
                && it2->lit2() < it2->lit3()
                && it2->learnt()
            ) {
                if (lit.sign()) votes[lit.var()] += 0.3;
                else votes[lit.var()] -= 0.3;

                Lit lit2 = it2->lit2();
                if (lit2.sign()) votes[lit2.var()] += 0.3;
                else votes[lit2.var()] -= 0.3;

                Lit lit3 = it2->lit3();
                if (lit3.sign()) votes[lit3.var()] += 0.3;
                else votes[lit3.var()] -= 0.3;
            }
        }
    }
}
void CalcDefPolars::add_vote(const Lit lit, const double value)
{
    if (lit.sign()) {
        votes[lit.var()] -= value;
    } else {
        votes[lit.var()] += value;
    }
}
Beispiel #7
0
bool VarReplacer::handleAlreadyReplaced(const Lit lit1, const Lit lit2)
{
    //OOps, already inside, but with inverse polarity, UNSAT
    if (lit1.sign() != lit2.sign()) {
        (*solver->drup)
        << ~lit1 << lit2 << fin
        << lit1 << ~lit2 << fin
        << lit1 << fin
        << ~lit1 << fin;

        solver->ok = false;
        return false;
    }

    //Already inside in the correct way, return
    return true;
}
void SolutionExtender::enqueue(const Lit lit)
{
    assigns[lit.var()] = boolToLBool(!lit.sign());
    trail.push_back(lit);
    #ifdef VERBOSE_DEBUG_RECONSTRUCT
    cout << "c Enqueueing lit " << lit << " during solution reconstruction" << endl;
    #endif
    solver->varData[lit.var()].level = std::numeric_limits< uint32_t >::max();
}
Beispiel #9
0
const bool DataSync::shareUnitData()
{
    uint32_t thisGotUnitData = 0;
    uint32_t thisSentUnitData = 0;

    SharedData& shared = *sharedData;
    shared.value.growTo(solver.nVars(), l_Undef);
    for (uint32_t var = 0; var < solver.nVars(); var++) {
        Lit thisLit = Lit(var, false);
        thisLit = solver.varReplacer->getReplaceTable()[thisLit.var()] ^ thisLit.sign();
        const lbool thisVal = solver.value(thisLit);
        const lbool otherVal = shared.value[var];

        if (thisVal == l_Undef && otherVal == l_Undef) continue;
        if (thisVal != l_Undef && otherVal != l_Undef) {
            if (thisVal != otherVal) {
                solver.ok = false;
                return false;
            } else {
                continue;
            }
        }

        if (otherVal != l_Undef) {
            assert(thisVal == l_Undef);
            Lit litToEnqueue = thisLit ^ (otherVal == l_False);
            if (solver.subsumer->getVarElimed()[litToEnqueue.var()]
                || solver.xorSubsumer->getVarElimed()[litToEnqueue.var()]
                ) continue;

            solver.uncheckedEnqueue(litToEnqueue);
            solver.ok = solver.propagate<false>().isNULL();
            if (!solver.ok) return false;
            thisGotUnitData++;
            continue;
        }

        if (thisVal != l_Undef) {
            assert(otherVal == l_Undef);
            shared.value[var] = thisVal;
            thisSentUnitData++;
            continue;
        }
    }

    if (solver.conf.verbosity >= 3 && (thisGotUnitData > 0 || thisSentUnitData > 0)) {
        std::cout << "c got units " << std::setw(8) << thisGotUnitData
        << " sent units " << std::setw(8) << thisSentUnitData << std::endl;
    }

    recvUnitData += thisGotUnitData;
    sentUnitData += thisSentUnitData;

    return true;
}
Beispiel #10
0
bool VarReplacer::update_table_and_reversetable(const Lit lit1, const Lit lit2)
{
    if (reverseTable.find(lit1.var()) == reverseTable.end()) {
        reverseTable[lit2.var()].push_back(lit1.var());
        table[lit1.var()] = lit2 ^ lit1.sign();
        replacedVars++;
        return true;
    }

    if (reverseTable.find(lit2.var()) == reverseTable.end()) {
        reverseTable[lit1.var()].push_back(lit2.var());
        table[lit2.var()] = lit1 ^ lit2.sign();
        replacedVars++;
        return true;
    }

    //both have children
    setAllThatPointsHereTo(lit1.var(), lit2 ^ lit1.sign());
    replacedVars++;
    return true;
}
Beispiel #11
0
void ImplCache::handleNewData(
    vector<uint16_t>& val
    , Var var
    , Lit lit
) {
    //Unfortunately, we cannot add the clauses, because that could mess up
    //the watchlists, which are being traversed by the callers, so we add these
    //new truths as delayed clauses, and add them at the end

    vector<Lit> tmp;

    //a->b and (-a)->b, so 'b'
    if  (val[lit.var()] == lit.sign()) {
        delayedClausesToAddNorm.push_back(lit);
        runStats.bProp++;
    } else {
        //a->b, and (-a)->(-b), so equivalent literal
        tmp.push_back(Lit(var, false));
        tmp.push_back(Lit(lit.var(), false));
        bool sign = lit.sign();
        delayedClausesToAddXor.push_back(std::make_pair(tmp, sign));
        runStats.bXProp++;
    }
}
Beispiel #12
0
/**
@brief Replaces vars in xorclauses
*/
bool VarReplacer::replace_set(vec<XorClause*>& cs)
{
    XorClause **a = cs.getData();
    XorClause **r = a;
    for (XorClause **end = a + cs.size(); r != end; r++) {
        XorClause& c = **r;

        bool changed = false;
        Var origVar1 = c[0].var();
        Var origVar2 = c[1].var();

        for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) {
            Lit newlit = table[l->var()];
            if (newlit.var() != l->var()) {
                changed = true;
                *l = Lit(newlit.var(), false);
                c.invert(newlit.sign());
                replacedLits++;
            }
        }

        if (changed && handleUpdatedClause(c, origVar1, origVar2)) {
            if (!solver.ok) {
                #ifdef VERBOSE_DEBUG
                cout << "contradiction while replacing lits in xor clause" << std::endl;
                #endif
                for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                cs.shrink(r-a);
                return false;
            }
            //solver.clauseAllocator.clauseFree(&c);
            c.setRemoved();
            solver.freeLater.push(&c);
        } else {
            #ifdef SILENT_DEBUG
            uint32_t numUndef = 0;
            for (uint32_t i = 0; i < c.size(); i++) {
                if (solver.value(c[i]) == l_Undef) numUndef++;
            }
            assert(numUndef >= 2 || numUndef == 0);
            #endif
            *a++ = *r;
        }
    }
    cs.shrink(r-a);

    return solver.ok;
}
Beispiel #13
0
const bool DataSync::syncBinFromOthers(const Lit lit, const vector<Lit>& bins, uint32_t& finished, vec<Watched>& ws)
{
    assert(solver.varReplacer->getReplaceTable()[lit.var()].var() == lit.var());
    assert(solver.subsumer->getVarElimed()[lit.var()] == false);
    assert(solver.xorSubsumer->getVarElimed()[lit.var()] == false);

    vec<Lit> addedToSeen;
    for (vec<Watched>::iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) {
        if (it->isBinary()) {
            addedToSeen.push(it->getOtherLit());
            seen[it->getOtherLit().toInt()] = true;
        }
    }

    vec<Lit> lits(2);
    for (uint32_t i = finished; i < bins.size(); i++) {
        if (!seen[bins[i].toInt()]) {
            Lit otherLit = bins[i];
            otherLit = solver.varReplacer->getReplaceTable()[otherLit.var()] ^ otherLit.sign();
            if (solver.subsumer->getVarElimed()[otherLit.var()]
                || solver.xorSubsumer->getVarElimed()[otherLit.var()]
                || solver.value(otherLit.var()) != l_Undef
                ) continue;

            recvBinData++;
            lits[0] = lit;
            lits[1] = otherLit;
            solver.addClauseInt(lits, 0, true, 2, 0, true);
            lits.clear();
            lits.growTo(2);
            if (!solver.ok) goto end;
        }
    }
    finished = bins.size();

    end:
    for (uint32_t i = 0; i < addedToSeen.size(); i++)
        seen[addedToSeen[i].toInt()] = false;

    return solver.ok;
}
Beispiel #14
0
/**
@brief Replaces variables in normal clauses
*/
const bool VarReplacer::replace_set(vec<Clause*>& cs, const bool binClauses)
{
    Clause **a = cs.getData();
    Clause **r = a;
    for (Clause **end = a + cs.size(); r != end; r++) {
        Clause& c = **r;
        bool changed = false;
        Lit origLit1 = c[0];
        Lit origLit2 = c[1];
        Lit origLit3 = (c.size() == 3) ? c[2] : lit_Undef;
        for (Lit *l = c.getData(), *end2 = l + c.size();  l != end2; l++) {
            if (table[l->var()].var() != l->var()) {
                changed = true;
                *l = table[l->var()] ^ l->sign();
                replacedLits++;
            }
        }

        if (changed && handleUpdatedClause(c, origLit1, origLit2, origLit3)) {
            if (!solver.ok) {
                for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                cs.shrink(r-a);
                return false;
            }
        } else {
            if (!binClauses && c.size() == 2) {
                solver.detachClause(c);
                Clause *c2 = solver.clauseAllocator.Clause_new(c);
                solver.clauseAllocator.clauseFree(&c);
                solver.attachClause(*c2);
                solver.becameBinary++;
                solver.binaryClauses.push(c2);
            } else
                *a++ = *r;
        }
    }
    cs.shrink(r-a);

    return solver.ok;
}
Beispiel #15
0
/**
@brief Replaces vars in xorclauses
*/
const bool VarReplacer::replace_set(vec<XorClause*>& cs)
{
    XorClause **a = cs.getData();
    XorClause **r = a;
    for (XorClause **end = a + cs.size(); r != end; r++) {
        XorClause& c = **r;

        bool changed = false;
        Var origVar1 = c[0].var();
        Var origVar2 = c[1].var();

        for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) {
            Lit newlit = table[l->var()];
            if (newlit.var() != l->var()) {
                changed = true;
                *l = Lit(newlit.var(), false);
                c.invert(newlit.sign());
                replacedLits++;
            }
        }

        if (changed && handleUpdatedClause(c, origVar1, origVar2)) {
            if (!solver.ok) {
                for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                cs.shrink(r-a);
                return false;
            }
            c.setRemoved();
            solver.freeLater.push(&c);
        } else {
            *a++ = *r;
        }
    }
    cs.shrink(r-a);

    return solver.ok;
}
Beispiel #16
0
/**
@brief Replaces variables in normal clauses
*/
bool VarReplacer::replace_set(vec<Clause*>& cs)
{
    Clause **a = cs.getData();
    Clause **r = a;
    for (Clause **end = a + cs.size(); r != end; r++) {
        Clause& c = **r;
        assert(c.size() > 2);
        bool changed = false;
        Lit origLit1 = c[0];
        Lit origLit2 = c[1];
        Lit origLit3 = (c.size() == 3) ? c[2] : lit_Undef;
        for (Lit *l = c.getData(), *end2 = l + c.size();  l != end2; l++) {
            if (table[l->var()].var() != l->var()) {
                changed = true;
                *l = table[l->var()] ^ l->sign();
                replacedLits++;
            }
        }

        if (changed && handleUpdatedClause(c, origLit1, origLit2, origLit3)) {
            if (!solver.ok) {
                #ifdef VERBOSE_DEBUG
                cout << "contradiction while replacing lits in normal clause" << std::endl;
                #endif
                for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                cs.shrink(r-a);
                return false;
            }
        } else {
            *a++ = *r;
        }
    }
    cs.shrink(r-a);

    return solver.ok;
}
Beispiel #17
0
// Propagating a literal. Type of literal and the (learned clause's)/(propagating clause's)/(etc) group must be given. Updates the proof graph and the statistics. note: the meaning of the variable 'group' depends on the type
void Logger::propagation(const Lit lit, Clause* c)
{
    first_begin();
    assert(!(proof == NULL && proof_graph_on));
    
    uint group;
    prop_type type;
    if (c == NULL) {
        if (S->decisionLevel() == 0)
            type = add_clause_type;
        else
            type = guess_type;
        group = std::numeric_limits<uint>::max();
    } else {
        type = simple_propagation_type;
        group = c->getGroup();
    }

    //graph
    if (proof_graph_on && (!mini_proof || type == guess_type)) {
        uniqueid++;
        
        fprintf(proof,"node%d [shape=box, label=\"",uniqueid);;
        if (lit.sign())
            fprintf(proof,"-");
        if (varnames[lit.var()] != "Noname")
            fprintf(proof,"%s\"];\n",varnames[lit.var()].c_str());
        else
            fprintf(proof,"Var: %d\"];\n",lit.var());

        fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid);
        
        switch (type) {
        case simple_propagation_type:
            fprintf(proof,"%s\"];\n", groupnames[group].c_str());
            break;
            
        case add_clause_type:
            fprintf(proof,"red. from clause\"];\n");
            break;
            
        case guess_type:
            fprintf(proof,"guess\",style=bold];\n");
            break;
        }
        history.push_back(uniqueid);
    }

    if (statistics_on) {
        switch (type) {
        case simple_propagation_type:
            depths_of_propagations_for_group[group].sum += S->decisionLevel();
            depths_of_propagations_for_group[group].num ++;
            if (S->decisionLevel() == 0) depths_of_propagations_unit[group] = true;
            times_group_caused_propagation[group]++;
        case add_clause_type:
            no_propagations++;
            times_var_propagated[lit.var()]++;
            depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
            depths_of_assigns_for_var[lit.var()].num ++;
            if (S->decisionLevel() == 0) depths_of_assigns_unit[lit.var()] = true;
            break;
        case guess_type:
            no_decisions++;
            times_var_guessed[lit.var()]++;
            
            depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
            depths_of_assigns_for_var[lit.var()].num ++;
            break;
        }
    }
}
Beispiel #18
0
void PropEngine::enqueue(const Lit p, const PropBy from)
{
    #ifdef DEBUG_ENQUEUE_LEVEL0
    #ifndef VERBOSE_DEBUG
    if (decisionLevel() == 0)
    #endif //VERBOSE_DEBUG
    cout << "enqueue var " << p.var()+1
    << " to val " << !p.sign()
    << " level: " << decisionLevel()
    << " sublevel: " << trail.size()
    << " by: " << from << endl;
    #endif //DEBUG_ENQUEUE_LEVEL0

    #ifdef ENQUEUE_DEBUG
    //assert(trail.size() <= nVarsOuter());
    //assert(decisionLevel() == 0 || varData[p.var()].removed == Removed::none);
    #endif

    const Var v = p.var();
    assert(value(v) == l_Undef);
    if (!watches[(~p).toInt()].empty()) {
        watches.prefetch((~p).toInt());
    }

    const bool sign = p.sign();
    assigns[v] = boolToLBool(!sign);
    #ifdef STATS_NEEDED_EXTRA
    varData[v].stats.trailLevelHist.push(trail.size());
    varData[v].stats.decLevelHist.push(decisionLevel());
    #endif
    varData[v].reason = from;
    varData[v].level = decisionLevel();

    trail.push_back(p);
    propStats.propagations++;
    if (update_bogoprops) {
        propStats.bogoProps += 1;
    }

    if (sign) {
        #ifdef STATS_NEEDED_EXTRA
        varData[v].stats.negPolarSet++;
        #endif

        #ifdef STATS_NEEDED
        propStats.varSetNeg++;
        #endif
    } else {
        #ifdef STATS_NEEDED_EXTRA
        varData[v].stats.posPolarSet++;
        #endif

        #ifdef STATS_NEEDED
        propStats.varSetPos++;
        #endif
    }

    if (varData[v].polarity != sign) {
        #ifdef UPDATE_AGILITY
        agility.update(true);
        #endif
        #ifdef STATS_NEEDED_EXTRA
        varData[v].stats.flippedPolarity++;
        #endif

        #ifdef STATS_NEEDED
        propStats.varFlipped++;
        #endif
    } else {
        #ifdef UPDATE_AGILITY
        agility.update(false);
        #endif
    }

    //Only update non-decision: this way, flipped decisions don't get saved
    if (update_polarity_and_activity
        && from != PropBy()
    ) {
        varData[v].polarity = !sign;
    }

    #ifdef ANIMATE3D
    std::cerr << "s " << v << " " << p.sign() << endl;
    #endif
}
Beispiel #19
0
void FeaturesCalc::for_one_clause(
    const Watched& cl
    , const Lit lit
    ,  Function func_each_cl
    ,  Function2 func_each_lit
) const {
    unsigned neg_vars = 0;
    unsigned pos_vars = 0;
    unsigned size = 0;

    switch (cl.getType()) {
        case CMSat::watch_binary_t: {
            if (cl.red()) {
                //only irred cls
                break;
            }
            if (lit > cl.lit2()) {
                //only count once
                break;
            }

            pos_vars += !lit.sign();
            pos_vars += !cl.lit2().sign();
            size = 2;
            neg_vars = size - pos_vars;
            func_each_cl(size, pos_vars, neg_vars);
            func_each_lit(lit, size, pos_vars, neg_vars);
            func_each_lit(cl.lit2(), size, pos_vars, neg_vars);
            break;
        }

        case CMSat::watch_tertiary_t: {
            if (cl.red()) {
                //only irred cls
                break;
            }
            if (lit > cl.lit2()) {
                //only count once
                break;
            }

            assert(cl.lit2() < cl.lit3());

            pos_vars += !lit.sign();
            pos_vars += !cl.lit2().sign();
            pos_vars += !cl.lit3().sign();
            size = 3;
            neg_vars = size - pos_vars;
            func_each_cl(size, pos_vars, neg_vars);
            func_each_lit(lit, size, pos_vars, neg_vars);
            func_each_lit(cl.lit2(), size, pos_vars, neg_vars);
            func_each_lit(cl.lit3(), size, pos_vars, neg_vars);
            break;
        }

        case CMSat::watch_clause_t: {
            const Clause& clause = *solver->cl_alloc.ptr(cl.get_offset());
            if (clause.red()) {
                //only irred cls
                break;
            }
            if (clause[0] < clause[1]) {
                //only count once
                break;
            }

            for (const Lit cl_lit : clause) {
                pos_vars += !cl_lit.sign();
            }
            size = clause.size();
            neg_vars = size - pos_vars;
            func_each_cl(size, pos_vars, neg_vars);
            for (const Lit cl_lit : clause) {
                func_each_lit(cl_lit, size, pos_vars, neg_vars);
            }
            break;
        }

        case CMSat::watch_idx_t: {
             // This should never be here
            assert(false);
            exit(-1);
            break;
        }
    }
}
Beispiel #20
0
void ImplCache::tryVar(
    Solver* solver
    , Var var
) {
    //Sanity check
    assert(solver->ok);
    assert(solver->decisionLevel() == 0);

    //Convenience
    vector<uint16_t>& seen = solver->seen;
    vector<uint16_t>& val = solver->seen2;

    Lit lit = Lit(var, false);

    const vector<LitExtra>& cache1 = implCache[lit.toInt()].lits;
    assert(solver->watches.size() > (lit.toInt()));
    watch_subarray_const ws1 = solver->watches[lit.toInt()];
    const vector<LitExtra>& cache2 = implCache[(~lit).toInt()].lits;
    watch_subarray_const ws2 = solver->watches[(~lit).toInt()];

    //Fill 'seen' and 'val' from cache
    for (vector<LitExtra>::const_iterator
        it = cache1.begin(), end = cache1.end()
        ; it != end
        ; it++
    ) {
        const Var var2 = it->getLit().var();

        //A variable that has been really eliminated, skip
        if (solver->varData[var2].removed != Removed::none
            && solver->varData[var2].removed != Removed::queued_replacer
        ) {
            continue;
        }

        seen[it->getLit().var()] = 1;
        val[it->getLit().var()] = it->getLit().sign();
    }

    //Fill 'seen' and 'val' from watch
    for (watch_subarray::const_iterator
        it = ws1.begin(), end = ws1.end()
        ; it != end
        ; it++
    ) {
        if (!it->isBinary())
            continue;

        const Lit otherLit = it->lit2();

        if (!seen[otherLit.var()]) {
            seen[otherLit.var()] = 1;
            val[otherLit.var()] = otherLit.sign();
        } else if (val[otherLit.var()] != otherLit.sign()) {
            //(a->b, a->-b) -> so 'a'
            delayedClausesToAddNorm.push_back(lit);
        }
    }
    //Okay, filled

    //Try to see if we propagate the same or opposite from the other end
    //Using cache
    for (vector<LitExtra>::const_iterator
        it = cache2.begin(), end = cache2.end()
        ; it != end
        ; it++
    ) {
        assert(it->getLit().var() != var);
        const Var var2 = it->getLit().var();

        //Only if the other one also contained it
        if (!seen[var2])
            continue;

        //If var has been removed, skip
        if (solver->varData[var2].removed != Removed::none
            && solver->varData[var2].removed != Removed::queued_replacer
        ) continue;

        handleNewData(val, var, it->getLit());
    }

    //Try to see if we propagate the same or opposite from the other end
    //Using binary clauses
    for (watch_subarray::const_iterator it = ws2.begin(), end = ws2.end(); it != end; it++) {
        if (!it->isBinary())
            continue;

        assert(it->lit2().var() != var);
        const Var var2 = it->lit2().var();
        assert(var2 < solver->nVars());

        //Only if the other one also contained it
        if (!seen[var2])
            continue;

        handleNewData(val, var, it->lit2());
    }

    //Clear 'seen' and 'val'
    for (vector<LitExtra>::const_iterator it = cache1.begin(), end = cache1.end(); it != end; it++) {
        seen[it->getLit().var()] = false;
        val[it->getLit().var()] = false;
    }

    for (watch_subarray::const_iterator it = ws1.begin(), end = ws1.end(); it != end; it++) {
        if (!it->isBinary())
            continue;

        seen[it->lit2().var()] = false;
        val[it->lit2().var()] = false;
    }
}
Beispiel #21
0
const bool VarReplacer::replace(T& ps, const bool xorEqualFalse, const uint32_t group)
{
    #ifdef VERBOSE_DEBUG
    std::cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xorEqualFalse " << xorEqualFalse << std::endl;
    #endif

    assert(ps.size() == 2);
    assert(!ps[0].sign());
    assert(!ps[1].sign());
    #ifdef DEBUG_REPLACER
    assert(solver.assigns[ps[0].var()].isUndef());
    assert(solver.assigns[ps[1].var()].isUndef());
    #endif

    Var var = ps[0].var();
    Lit lit = Lit(ps[1].var(), !xorEqualFalse);
    assert(var != lit.var());

    //Detect circle
    if (alreadyIn(var, lit)) return solver.ok;

    Lit lit1 = table[var];
    bool inverted = false;

    //This pointer is already set, try to invert
    if (lit1.var() != var) {
        Var tmp_var = var;

        var = lit.var();
        lit = Lit(tmp_var, lit.sign());
        inverted = true;
    }

    if (inverted) {
        Lit lit2 = table[var];

        //Inversion is also set, triangular cycle
        //A->B, A->C, B->C. There is nothing to add
        if (lit1.var() == lit2.var()) {
            if ((lit1.sign() ^ lit2.sign()) != lit.sign()) {
                #ifdef VERBOSE_DEBUG
                cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
                #endif
                return (solver.ok = false);
            }
            return true;
        }

        //Inversion is also set
        if (lit2.var() != var) {
            assert(table[lit1.var()].var() == lit1.var());
            setAllThatPointsHereTo(lit1.var(), Lit(lit.var(), lit1.sign()));

            assert(table[lit2.var()].var() == lit2.var());
            setAllThatPointsHereTo(lit2.var(), lit ^ lit2.sign());

            table[lit.var()] = Lit(lit.var(), false);
            replacedVars++;
            addBinaryXorClause(ps, xorEqualFalse, group);
            return true;
        }
    }

    //Follow forwards
    Lit litX = table[lit.var()];
    if (litX.var() != lit.var())
        lit = litX ^ lit.sign();

    //Follow backwards
    setAllThatPointsHereTo(var, lit);
    replacedVars++;
    addBinaryXorClause(ps, xorEqualFalse, group);

    return true;
}
Beispiel #22
0
Lit VarReplacer::getLitReplacedWithOuter(Lit lit) const
{
    Lit lit2 = table[lit.var()] ^ lit.sign();
    return lit2;
}
Beispiel #23
0
/**
@brief The main function of search() doing almost everything in this class

Tries to branch on both lit1 and lit2 and then both-propagates them, fail-lits
them, and hyper-bin resolves them, etc. It is imperative that from the
SAT point of view, EITHER lit1 or lit2 MUST hold. So, if lit1 = ~lit2, it's OK.
Also, if there is a binary clause 'lit1 or lit2' it's also OK.
 */
bool FailedLitSearcher::tryBoth(const Lit lit1, const Lit lit2) {
    if (binXorFind) {
        if (lastTrailSize < solver.trail.size()) {
            for (uint32_t i = lastTrailSize; i != solver.trail.size(); i++) {
                removeVarFromXors(solver.trail[i].var());
            }
        }
        lastTrailSize = solver.trail.size();
        xorClauseTouched.setZero();
        investigateXor.clear();
    }

    propagated.removeThese(propagatedBitSet);
#ifdef DEBUG_FAILEDLIT
    assert(propagated.isZero());
#endif
    propagatedBitSet.clear();
    twoLongXors.clear();
    bothSame.clear();
    binXorToAdd.clear();
#ifdef DEBUG_HYPERBIN
    assert(propagatedVars.empty());
    assert(unPropagatedBin.isZero());
#endif //DEBUG_HYPERBIN
#ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
    dontRemoveAncestor.isZero();
    assert(uselessBin.empty());
#endif

    solver.newDecisionLevel();
    solver.uncheckedEnqueueLight(lit1);
    failed = (!solver.propagate<false>(false).isNULL());
    if (failed) {
        solver.cancelUntilLight();
        numFailed++;
        solver.uncheckedEnqueue(~lit1);
        solver.ok = (solver.propagate<false>(false).isNULL());
        if (!solver.ok) return false;
        return true;
    }

    assert(solver.decisionLevel() > 0);
    Solver::TransCache& lit1OTFCache = solver.transOTFCache[(~lit1).toInt()];
    if (solver.conf.doCacheOTFSSR) {
        lit1OTFCache.conflictLastUpdated = solver.conflicts;
        lit1OTFCache.lits.clear();
    }
    for (int c = solver.trail.size() - 1; c >= (int) solver.trail_lim[0]; c--) {
        Var x = solver.trail[c].var();
        propagated.setBit(x);
        propagatedBitSet.push_back(x);

        if (solver.conf.doHyperBinRes) {
            unPropagatedBin.setBit(x);
            propagatedVars.push(x);
        }

        if (solver.assigns[x].getBool()) propValue.setBit(x);
        else propValue.clearBit(x);

        if (binXorFind) removeVarFromXors(x);
        if (solver.conf.doCacheOTFSSR && c != (int) solver.trail_lim[0]) {
            lit1OTFCache.lits.push_back(solver.trail[c]);
        }
    }

    if (binXorFind) {
        for (uint32_t *it = investigateXor.getData(), *end = investigateXor.getDataEnd(); it != end; it++) {
            if (xorClauseSizes[*it] == 2)
                twoLongXors.insert(getTwoLongXor(*solver.xorclauses[*it]));
        }
        for (int c = solver.trail.size() - 1; c >= (int) solver.trail_lim[0]; c--) {
            addVarFromXors(solver.trail[c].var());
        }
        xorClauseTouched.setZero();
        investigateXor.clear();
    }

    solver.cancelUntilLight();

    //Hyper-binary resolution, and its accompanying data-structure cleaning
    if (solver.conf.doHyperBinRes) {
        if (hyperbinProps < maxHyperBinProps) hyperBinResolution(lit1);
        unPropagatedBin.removeThese(propagatedVars);
        propagatedVars.clear();
    }

#ifdef DEBUG_HYPERBIN
    assert(propagatedVars.empty());
    assert(unPropagatedBin.isZero());
#endif //DEBUG_HYPERBIN

    solver.newDecisionLevel();
    solver.uncheckedEnqueueLight(lit2);
    failed = (!solver.propagate<false>(false).isNULL());
    if (failed) {
        solver.cancelUntilLight();
        numFailed++;
        solver.uncheckedEnqueue(~lit2);
        solver.ok = (solver.propagate<false>(false).isNULL());
        if (!solver.ok) return false;
        return true;
    }

    assert(solver.decisionLevel() > 0);
    Solver::TransCache& lit2OTFCache = solver.transOTFCache[(~lit2).toInt()];
    if (solver.conf.doCacheOTFSSR) {
        lit2OTFCache.conflictLastUpdated = solver.conflicts;
        lit2OTFCache.lits.clear();
    }
    for (int c = solver.trail.size() - 1; c >= (int) solver.trail_lim[0]; c--) {
        Var x = solver.trail[c].var();
        if (propagated[x]) {
            if (propValue[x] == solver.assigns[x].getBool()) {
                //they both imply the same
                bothSame.push(Lit(x, !propValue[x]));
            } else if (c != (int) solver.trail_lim[0]) {
                bool invert;
                if (lit1.var() == lit2.var()) {
                    assert(lit1.sign() == false && lit2.sign() == true);
                    tmpPs[0] = Lit(lit1.var(), false);
                    tmpPs[1] = Lit(x, false);
                    invert = propValue[x];
                } else {
                    tmpPs[0] = Lit(lit1.var(), false);
                    tmpPs[1] = Lit(lit2.var(), false);
                    invert = lit1.sign() ^ lit2.sign();
                }
                binXorToAdd.push_back(BinXorToAdd(tmpPs[0], tmpPs[1], invert));
                bothInvert += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
                toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
            }
        }

        if (solver.conf.doHyperBinRes) {
            unPropagatedBin.setBit(x);
            propagatedVars.push(x);
        }

        if (solver.assigns[x].getBool()) propValue.setBit(x);
        else propValue.clearBit(x);

        if (binXorFind) removeVarFromXors(x);
        if (solver.conf.doCacheOTFSSR && c != (int) solver.trail_lim[0]) {
            lit2OTFCache.lits.push_back(solver.trail[c]);
        }
    }

    //We now add the two-long xors that have been found through longer
    //xor-shortening
    if (binXorFind) {
        if (twoLongXors.size() > 0) {
            for (uint32_t *it = investigateXor.getData(), *end = it + investigateXor.size(); it != end; it++) {
                if (xorClauseSizes[*it] == 2) {
                    TwoLongXor tmp = getTwoLongXor(*solver.xorclauses[*it]);
                    if (twoLongXors.find(tmp) != twoLongXors.end()) {
                        tmpPs[0] = Lit(tmp.var[0], false);
                        tmpPs[1] = Lit(tmp.var[1], false);
                        binXorToAdd.push_back(BinXorToAdd(tmpPs[0], tmpPs[1], tmp.inverted));
                        newBinXor += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
                        toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
                    }
                }
            }
        }
        for (int c = solver.trail.size() - 1; c >= (int) solver.trail_lim[0]; c--) {
            addVarFromXors(solver.trail[c].var());
        }
    }
    solver.cancelUntilLight();

    if (solver.conf.doHyperBinRes) {
        if (hyperbinProps < maxHyperBinProps) hyperBinResolution(lit2);
        unPropagatedBin.removeThese(propagatedVars);
        propagatedVars.clear();
    }

    for (uint32_t i = 0; i != bothSame.size(); i++) {
        solver.uncheckedEnqueue(bothSame[i]);
    }
    goodBothSame += bothSame.size();
    solver.ok = (solver.propagate<false>(false).isNULL());
    if (!solver.ok) return false;

    if (solver.conf.doBXor) {
        for (uint32_t i = 0; i < binXorToAdd.size(); i++) {
            tmpPs[0] = binXorToAdd[i].lit1;
            tmpPs[1] = binXorToAdd[i].lit2;
            solver.addXorClauseInt(tmpPs, binXorToAdd[i].isEqualFalse);
            tmpPs.clear();
            tmpPs.growTo(2);
            if (!solver.ok) return false;
        }
    }

    return true;
}