Beispiel #1
0
    bool BothCache::tryBoth() {
        vec<bool> seen(solver.nVars(), 0);
        vec<bool> val(solver.nVars(), 0);
        vec<Lit> tmp;
        uint32_t bProp = 0;
        uint32_t bXProp = 0;
        double myTime = cpuTime();
        uint32_t backupTrailSize = solver.trail.size();

        for (Var var = 0; var < solver.nVars(); var++) {
            if (solver.value(var) != l_Undef
                    || (solver.subsumer && solver.subsumer->getVarElimed()[var])
                    || solver.xorSubsumer->getVarElimed()[var]
                    || solver.varReplacer->getReplaceTable()[var].var() != var)
                continue;

            Lit lit = Lit(var, false);
            vector<Lit> const* cache1;
            vector<Lit> const* cache2;

            bool startWithTrue;
            if (solver.transOTFCache[lit.toInt()].lits.size() < solver.transOTFCache[(~lit).toInt()].lits.size()) {
                cache1 = &solver.transOTFCache[lit.toInt()].lits;
                cache2 = &solver.transOTFCache[(~lit).toInt()].lits;
                startWithTrue = false;
            } else {
                cache1 = &solver.transOTFCache[(~lit).toInt()].lits;
                cache2 = &solver.transOTFCache[lit.toInt()].lits;
                startWithTrue = true;
            }

            if (cache1->size() == 0) continue;

            for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) {
                seen[it->var()] = true;
                val[it->var()] = it->sign();
            }

            for (vector<Lit>::const_iterator it = cache2->begin(), end = cache2->end(); it != end; it++) {
                if (seen[it->var()]) {
                    Var var2 = it->var();
                    if ((solver.subsumer && solver.subsumer->getVarElimed()[var2])
                            || solver.xorSubsumer->getVarElimed()[var2]
                            || solver.varReplacer->getReplaceTable()[var2].var() != var2)
                        continue;

                    if (val[it->var()] == it->sign()) {
                        tmp.clear();
                        tmp.push(*it);
                        solver.addClauseInt(tmp, true);
                        if (!solver.ok) goto end;
                        bProp++;
                    } else {
                        tmp.clear();
                        tmp.push(Lit(var, false));
                        tmp.push(Lit(it->var(), false));
                        bool sign = true ^ startWithTrue ^ it->sign();
                        solver.addXorClauseInt(tmp, sign);
                        if (!solver.ok) goto end;
                        bXProp++;
                    }
                }
            }

            for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) {
                seen[it->var()] = false;
            }
        }

end:
        if (solver.conf.verbosity >= 1) {
            std::cout << "c Cache " <<
                    " BProp: " << bProp <<
                    " Set: " << (solver.trail.size() - backupTrailSize) <<
                    " BXProp: " << bXProp <<
                    " T: " << (cpuTime() - myTime) <<
                    std::endl;
        }

        return solver.ok;
    }
Lit HyperEngine::propagate_bfs(const uint64_t timeout)
{
    timedOutPropagateFull = false;
    propStats.otfHyperPropCalled++;
    #ifdef VERBOSE_DEBUG_FULLPROP
    cout << "Prop full BFS started" << endl;
    #endif

    PropBy confl;

    //Assert startup: only 1 enqueued, uselessBin is empty
    assert(uselessBin.empty());
    //assert(decisionLevel() == 1);

    //The toplevel decision has to be set specifically
    //If we came here as part of a backtrack to decision level 1, then
    //this is already set, and there is no need to set it
    if (trail.size() - trail_lim.back() == 1) {
        //Set up root node
        Lit root = trail[qhead];
        varData[root.var()].reason = PropBy(~lit_Undef, false, false, false);
    }

    uint32_t nlBinQHead = qhead;
    uint32_t lBinQHead = qhead;

    needToAddBinClause.clear();
    PropResult ret = PROP_NOTHING;
    start:

    //Early-abort if too much time was used (from prober)
    if (propStats.otfHyperTime + propStats.bogoProps > timeout) {
        timedOutPropagateFull = true;
        return lit_Undef;
    }

    //Propagate binary irred
    while (nlBinQHead < trail.size()) {
        const Lit p = trail[nlBinQHead++];
        watch_subarray_const ws = watches[~p];
        propStats.bogoProps += 1;
        for(const Watched *k = ws.begin(), *end = ws.end()
            ; k != end
            ; k++
        ) {

            //If something other than irred binary, skip
            if (!k->isBin() || k->red())
                continue;

            ret = prop_bin_with_ancestor_info(p, k, confl);
            if (ret == PROP_FAIL)
                return analyzeFail(confl);

        }
        propStats.bogoProps += ws.size()*4;
    }

    //Propagate binary redundant
    ret = PROP_NOTHING;
    while (lBinQHead < trail.size()) {
        const Lit p = trail[lBinQHead];
        watch_subarray_const ws = watches[~p];
        propStats.bogoProps += 1;
        size_t done = 0;

        for(const Watched *k = ws.begin(), *end = ws.end(); k != end; k++, done++) {

            //If something other than redundant binary, skip
            if (!k->isBin() || !k->red())
                continue;

            ret = prop_bin_with_ancestor_info(p, k, confl);
            if (ret == PROP_FAIL) {
                return analyzeFail(confl);
            } else if (ret == PROP_SOMETHING) {
                propStats.bogoProps += done*4;
                goto start;
            } else {
                assert(ret == PROP_NOTHING);
            }
        }
        lBinQHead++;
        propStats.bogoProps += done*4;
    }

    ret = PROP_NOTHING;
    while (qhead < trail.size()) {
        const Lit p = trail[qhead];
        watch_subarray ws = watches[~p];
        propStats.bogoProps += 1;

        Watched* i = ws.begin();
        Watched* j = ws.begin();
        Watched* end = ws.end();
        for(; i != end; i++) {
            if (i->isBin()) {
                *j++ = *i;
                continue;
            }

            if (i->isTri()) {
                *j++ = *i;
                ret = prop_tri_clause_with_acestor_info(i, p, confl);
                if (ret == PROP_SOMETHING || ret == PROP_FAIL) {
                    i++;
                    break;
                } else {
                    assert(ret == PROP_NOTHING);
                    continue;
                }
            }

            if (i->isClause()) {
                ret = prop_normal_cl_with_ancestor_info(i, j, p, confl);
                if (ret == PROP_SOMETHING || ret == PROP_FAIL) {
                    i++;
                    break;
                } else {
                    assert(ret == PROP_NOTHING);
                    continue;
                }
            }
        }
        propStats.bogoProps += ws.size()*4;
        while(i != end)
            *j++ = *i++;
        ws.shrink_(end-j);

        if (ret == PROP_FAIL) {
            return analyzeFail(confl);
        } else if (ret == PROP_SOMETHING) {
            propStats.bogoProps += ws.size()*4;
            goto start;
        }

        qhead++;
        propStats.bogoProps += ws.size()*4;
    }

    return lit_Undef;
}
/**
We can try both ways: either binary clause can be removed.
Try to remove one, then the other
Return which one is to be removed
*/
Lit HyperEngine::remove_which_bin_due_to_trans_red(
    Lit conflict
    , Lit thisAncestor
    , bool thisStepRed
) {
    propStats.otfHyperTime += 1;
    const PropBy& data = varData[conflict.var()].reason;

    bool onlyIrred = !data.isRedStep();
    Lit lookingForAncestor = data.getAncestor();

    if (thisAncestor == lit_Undef || lookingForAncestor == lit_Undef)
        return lit_Undef;

    propStats.otfHyperTime += 1;
    bool second_is_deeper = false;
    bool ambivalent = true;
    if (use_depth_trick) {
        ambivalent = depth[thisAncestor.var()] == depth[lookingForAncestor.var()];
        if (depth[thisAncestor.var()] < depth[lookingForAncestor.var()]) {
            second_is_deeper = true;
        }
    }
    #ifdef DEBUG_DEPTH
    cout
    << "1st: " << std::setw(6) << thisAncestor
    << " depth: " << std::setw(4) << depth[thisAncestor.var()]
    << "  2nd: " << std::setw(6) << lookingForAncestor
    << " depth: " << std::setw(4) << depth[lookingForAncestor.var()]
    ;
    #endif


    if ((ambivalent || !second_is_deeper) &&
        is_ancestor_of(
        conflict
        , thisAncestor
        , thisStepRed
        , onlyIrred
        , lookingForAncestor
        )
    ) {
        #ifdef DEBUG_DEPTH
        cout << " -- OK" << endl;
        #endif
        //assert(ambivalent || !second_is_deeper);
        return thisAncestor;
    }

    onlyIrred = !thisStepRed;
    thisStepRed = data.isRedStep();
    std::swap(lookingForAncestor, thisAncestor);
    if ((ambivalent || second_is_deeper) &&
        is_ancestor_of(
        conflict
        , thisAncestor
        , thisStepRed
        , onlyIrred
        , lookingForAncestor
        )
    ) {
        #ifdef DEBUG_DEPTH
        cout << " -- OK" << endl;
        #endif
        //assert(ambivalent || second_is_deeper);
        return thisAncestor;
    }

    #ifdef DEBUG_DEPTH
    cout << " -- NOTK" << endl;
    #endif

    return lit_Undef;
}
Beispiel #4
0
const bool MatrixFinder::findMatrixes()
{
    table.clear();
    table.resize(solver.nVars(), var_Undef);
    reverseTable.clear();
    matrix_no = 0;
    double myTime = cpuTime();

    if (solver.xorclauses.size() < MIN_GAUSS_XOR_CLAUSES ||
            solver.gaussconfig.decision_until <= 0 ||
            solver.xorclauses.size() > MAX_GAUSS_XOR_CLAUSES
       )
        return true;

    solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
    if (!solver.ok) return false;

    if (solver.gaussconfig.noMatrixFind) {
        if (solver.verbosity >=1)
            cout << "c Matrix finding disabled through switch. Putting all xors into matrix." << endl;
        vector<XorClause*> xorclauses;
        xorclauses.reserve(solver.xorclauses.size());
        for (uint32_t i = 0; i < solver.xorclauses.size(); i++)
            xorclauses.push_back(solver.xorclauses[i]);
        solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, 0, xorclauses));
        return true;
    }

    for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
        set<uint32_t> tomerge;
        vector<Var> newSet;
        for (Lit *l = &(**c)[0], *end2 = l + (**c).size(); l != end2; l++) {
            if (table[l->var()] != var_Undef)
                tomerge.insert(table[l->var()]);
            else
                newSet.push_back(l->var());
        }
        if (tomerge.size() == 1) {
            const uint32_t into = *tomerge.begin();
            map<uint32_t, vector<Var> >::iterator intoReverse = reverseTable.find(into);
            for (uint32_t i = 0; i < newSet.size(); i++) {
                intoReverse->second.push_back(newSet[i]);
                table[newSet[i]] = into;
            }
            continue;
        }

        for (set<uint32_t>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
            newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end());
            reverseTable.erase(*it);
        }
        for (uint32_t i = 0; i < newSet.size(); i++)
            table[newSet[i]] = matrix_no;
        reverseTable[matrix_no] = newSet;
        matrix_no++;
    }

#ifdef VERBOSE_DEBUG
    for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
        cout << "-- set begin --" << endl;
        for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
            cout << *it2 << ", ";
        }
        cout << "-------" << endl;
    }
#endif

    uint32_t numMatrixes = setMatrixes();

    if (solver.verbosity >=1)
        std::cout << "c Finding matrixes :    " << cpuTime() - myTime
                  << " s (found  " << numMatrixes << ")"
                  << endl;

    for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end = solver.gauss_matrixes.end(); gauss != end; gauss++) {
        if (!(*gauss)->full_init()) return false;
    }

    return true;
}
Beispiel #5
0
void BVA::fill_potential(const Lit lit)
{
    for(const OccurClause& c: m_cls) {
        if (*simplifier->limit_to_decrease < 0)
            break;

        const Lit l_min = least_occurring_except(c);
        if (l_min == lit_Undef)
            continue;

        solver->watches.prefetch(l_min.toInt());
        m_lits_this_cl = m_lits;
        *simplifier->limit_to_decrease -= m_lits_this_cl.size();
        for(const lit_pair lits: m_lits_this_cl) {
            seen2[lits.hash(seen2.size())] = 1;
        }

        if (solver->conf.verbosity >= 6 || bva_verbosity) {
            cout
            << "c [occ-bva] Examining clause for addition to 'potential':"
            << solver->watched_to_string(c.lit, c.ws)
            << " -- Least occurring in this CL: " << l_min
            << endl;
        }

        *simplifier->limit_to_decrease -= (long)solver->watches[l_min].size()*3;
        for(const Watched& d_ws: solver->watches[l_min]) {
            if (*simplifier->limit_to_decrease < 0)
                goto end;

            OccurClause d(l_min, d_ws);
            const size_t sz_c = solver->cl_size(c.ws);
            const size_t sz_d = solver->cl_size(d.ws);
            if (c.ws != d.ws
                && (sz_c == sz_d
                    || (sz_c+1 == sz_d
                        && solver->conf.bva_also_twolit_diff
                        && (long)solver->sumConflicts() >= solver->conf.bva_extra_lit_and_red_start
                    )
                )
                && !solver->redundant(d.ws)
                && lit_diff_watches(c, d) == lit
            ) {
                const lit_pair diff = lit_diff_watches(d, c);
                if (seen2[diff.hash(seen2.size())] == 0) {
                    *simplifier->limit_to_decrease -= 3;
                    potential.push_back(PotentialClause(diff, c));
                    m_lits_this_cl.push_back(diff);
                    seen2[diff.hash(seen2.size())] = 1;

                    if (solver->conf.verbosity >= 6 || bva_verbosity) {
                        cout
                        << "c [occ-bva] Added to P: "
                        << potential.back().to_string(solver)
                        << endl;
                    }
                }
            }
        }

        end:
        for(const lit_pair lits: m_lits_this_cl) {
            seen2[lits.hash(seen2.size())] = 0;
        }
    }
}
/**
@brief If needed, compacts stacks, removing unused clauses

Firstly, the algorithm determines if the number of useless slots is large or
small compared to the problem size. If it is small, it does nothing. If it is
large, then it allocates new stacks, copies the non-freed clauses to these new
stacks, updates all pointers and offsets, and frees the original stacks.
*/
void ClauseAllocator::consolidate(
    Solver* solver
    , const bool force
    , bool lower_verb
) {
    //If re-allocation is not really neccessary, don't do it
    //Neccesities:
    //1) There is too much memory allocated. Re-allocation will save space
    //   Avoiding segfault (max is 16 outerOffsets, more than 10 is near)
    //2) There is too much empty, unused space (>30%)
    if (!force
        && (float_div(currentlyUsedSize, size) > 0.8 || currentlyUsedSize < (100ULL*1000ULL))
    ) {
        if (solver->conf.verbosity >= 3
            || (lower_verb && solver->conf.verbosity)
        ) {
            cout << "c Not consolidating memory." << endl;
        }
        return;
    }
    const double myTime = cpuTime();

    //Pointers that will be moved along
    BASE_DATA_TYPE * const newDataStart = (BASE_DATA_TYPE*)malloc(currentlyUsedSize*sizeof(BASE_DATA_TYPE));
    BASE_DATA_TYPE * new_ptr = newDataStart;

    assert(sizeof(BASE_DATA_TYPE) % sizeof(Lit) == 0);

    vector<bool> visited(solver->watches.size(), 0);
    Heap<Solver::VarOrderLt> &order_heap = solver->VSIDS ? solver->order_heap_vsids : solver->order_heap_maple;
    if (solver->conf.static_mem_consolidate_order) {
        for(auto& ws: solver->watches) {
            move_one_watchlist(ws, newDataStart, new_ptr);
        }
    } else {
        for(uint32_t i = 0; i < order_heap.size(); i++) {
            for(uint32_t i2 = 0; i2 < 2; i2++) {
                Lit lit = Lit(order_heap[i], i2);
                assert(lit.toInt() < solver->watches.size());
                move_one_watchlist(solver->watches[lit], newDataStart, new_ptr);
                visited[lit.toInt()] = 1;
            }
        }
        for(uint32_t i = 0; i < solver->watches.size(); i++) {
            Lit lit = Lit::toLit(i);
            watch_subarray ws = solver->watches[lit];
            if (!visited[lit.toInt()]) {
                move_one_watchlist(ws, newDataStart, new_ptr);
                visited[lit.toInt()] = 1;
            }
        }
    }

    #ifdef USE_GAUSS
    for (EGaussian* gauss : solver->gmatrixes) {
        if (gauss == NULL) {
            continue;
        }

        for(auto& gcl: gauss->clauses_toclear) {
            Clause* old = ptr(gcl.first);
            if (old->reloced) {
                ClOffset new_offset = (*old)[0].toInt();
                #ifdef LARGE_OFFSETS
                new_offset += ((uint64_t)(*old)[1].toInt())<<32;
                #endif
                gcl.first = new_offset;
            } else {
                ClOffset new_offset = move_cl(newDataStart, new_ptr, old);
                gcl.first = new_offset;
            }
            assert(!old->freed());
        }
    }
    #endif //USE_GAUSS

    update_offsets(solver->longIrredCls);
    for(auto& lredcls: solver->longRedCls) {
        update_offsets(lredcls);
    }

    //Fix up propBy
    for (size_t i = 0; i < solver->nVars(); i++) {
        VarData& vdata = solver->varData[i];
        if (vdata.reason.isClause()) {
            if (vdata.removed == Removed::none
                && solver->decisionLevel() >= vdata.level
                && vdata.level != 0
                && solver->value(i) != l_Undef
            ) {
                Clause* old = ptr(vdata.reason.get_offset());
                assert(!old->freed());
                ClOffset new_offset = (*old)[0].toInt();
                #ifdef LARGE_OFFSETS
                new_offset += ((uint64_t)(*old)[1].toInt())<<32;
                #endif
                vdata.reason = PropBy(new_offset);
            } else {
                vdata.reason = PropBy();
            }
        }
    }

    //Update sizes
    const uint64_t old_size = size;
    size = new_ptr-newDataStart;
    capacity = currentlyUsedSize;
    currentlyUsedSize = size;
    free(dataStart);
    dataStart = newDataStart;

    const double time_used = cpuTime() - myTime;
    if (solver->conf.verbosity >= 2
        || (lower_verb && solver->conf.verbosity)
    ) {
        size_t log_2_size = 0;
        if (size > 0) {
            //yes, it can be 0 (only binary clauses, for example)
            std::log2(size);
        }
        cout << "c [mem] consolidate ";
        cout << " old-sz: "; print_value_kilo_mega(old_size*sizeof(BASE_DATA_TYPE));
        cout << " new-sz: "; print_value_kilo_mega(size*sizeof(BASE_DATA_TYPE));
        cout << " new bits offs: " << std::fixed << std::setprecision(2) << log_2_size;
        cout << solver->conf.print_times(time_used)
        << endl;
    }
    if (solver->sqlStats) {
        solver->sqlStats->time_passed_min(
            solver
            , "consolidate"
            , time_used
        );
    }
}
Beispiel #7
0
 inline Lit comp(const Lit x) {
   return x.comp();
 }
Beispiel #8
0
void SubsumeImplicit::subsume_implicit(const bool check_stats)
{
    assert(solver->okay());
    const double myTime = cpuTime();
    timeAvailable = 1900LL*1000LL*1000LL;
    const bool doStamp = solver->conf.doStamp;
    runStats.clear();

    //Randomize starting point
    const size_t rnd_start = solver->mtrand.randInt(solver->watches.size()-1);
    size_t numDone = 0;
    for (;numDone < solver->watches.size() && timeAvailable > 0
         ;numDone++
    ) {
        const size_t at = (rnd_start + numDone)  % solver->watches.size();
        runStats.numWatchesLooked++;
        const Lit lit = Lit::toLit(at);
        watch_subarray ws = solver->watches[lit.toInt()];

        //We can't do much when there is nothing, or only one
        if (ws.size() < 2)
            continue;

        if (ws.size() > 1) {
            timeAvailable -= ws.size()*std::ceil(std::log((double)ws.size())) + 20;
            std::sort(ws.begin(), ws.end(), WatchSorter());
        }
        /*cout << "---> Before" << endl;
        printWatchlist(ws, lit);*/

        Watched* i = ws.begin();
        Watched* j = i;
        clear();

        for (Watched* end = ws.end(); i != end; i++) {
            if (timeAvailable < 0) {
                *j++ = *i;
                continue;
            }

            switch(i->getType()) {
                case CMSat::watch_clause_t:
                    *j++ = *i;
                    break;

                case CMSat::watch_tertiary_t:
                    try_subsume_tri(lit, i, j, doStamp);
                    break;

                case CMSat::watch_binary_t:
                    try_subsume_bin(lit, i, j);
                    break;

                default:
                    assert(false);
                    break;
            }
        }
        ws.shrink(i-j);
    }
    if (check_stats) {
        solver->checkStats();
    }

    runStats.numCalled++;
    runStats.time_used += cpuTime() - myTime;
    runStats.time_out += (timeAvailable <= 0);
    if (solver->conf.verbosity >= 1) {
        runStats.printShort();
    }

    globalStats += runStats;
}
void SubsumeImplicit::subsume_implicit(const bool check_stats)
{
    assert(solver->okay());
    const double myTime = cpuTime();
    const uint64_t orig_timeAvailable =
        1000LL*1000LL*solver->conf.subsume_implicit_time_limitM
        *solver->conf.global_timeout_multiplier;
    timeAvailable = orig_timeAvailable;
    const bool doStamp = solver->conf.doStamp;
    runStats.clear();

    //For randomization, we must have at least 1
    if (solver->watches.size() == 0) {
        return;
    }

    //Randomize starting point
    const size_t rnd_start = solver->mtrand.randInt(solver->watches.size()-1);
    size_t numDone = 0;
    for (;numDone < solver->watches.size() && timeAvailable > 0 && !solver->must_interrupt_asap()
         ;numDone++
    ) {
        const size_t at = (rnd_start + numDone)  % solver->watches.size();
        runStats.numWatchesLooked++;
        const Lit lit = Lit::toLit(at);
        watch_subarray ws = solver->watches[lit.toInt()];

        //We can't do much when there is nothing, or only one
        if (ws.size() < 2)
            continue;

        if (ws.size() > 1) {
            timeAvailable -= ws.size()*std::ceil(std::log((double)ws.size())) + 20;
            std::sort(ws.begin(), ws.end(), WatchSorterBinTriLong());
        }
        /*cout << "---> Before" << endl;
        print_watch_list(ws, lit);*/

        Watched* i = ws.begin();
        Watched* j = i;
        clear();

        for (Watched* end = ws.end(); i != end; i++) {
            if (timeAvailable < 0) {
                *j++ = *i;
                continue;
            }

            switch(i->getType()) {
                case CMSat::watch_clause_t:
                    *j++ = *i;
                    break;

                case CMSat::watch_tertiary_t:
                    try_subsume_tri(lit, i, j, doStamp);
                    break;

                case CMSat::watch_binary_t:
                    try_subsume_bin(lit, i, j);
                    break;

                default:
                    assert(false);
                    break;
            }
        }
        ws.shrink(i-j);
    }

    const double time_used = cpuTime() - myTime;
    const bool time_out = (timeAvailable <= 0);
    const double time_remain = float_div(timeAvailable, orig_timeAvailable);
    runStats.numCalled++;
    runStats.time_used += time_used;
    runStats.time_out += time_out;
    if (solver->conf.verbosity >= 1) {
        runStats.print_short(solver);
    }
    if (solver->sqlStats) {
        solver->sqlStats->time_passed(
            solver
            , "subsume implicit"
            , time_used
            , time_out
            , time_remain
        );
    }

    if (check_stats) {
        #ifdef DEBUG_IMPLICIT_STATS
        solver->check_stats();
        #endif
    }

    globalStats += runStats;
}
Beispiel #10
0
bool Prober::probe()
{
    assert(solver->decisionLevel() == 0);
    assert(solver->nVars() > 0);

    uint64_t numPropsTodo = 2000L*1000L*1000L;

    solver->testAllClauseAttach();
    const double myTime = cpuTime();
    const size_t origTrailSize = solver->trail.size();
    solver->clauseCleaner->removeAndCleanAll();

    //Stats
    extraTime = 0;
    solver->propStats.clear();
    runStats.clear();
    runStats.origNumFreeVars = solver->getNumFreeVars();
    runStats.origNumBins = solver->binTri.redBins + solver->binTri.irredBins;
    numCalls++;

    //State
    visitedAlready.clear();
    visitedAlready.resize(solver->nVars()*2, 0);
    propagatedBitSet.clear();
    propagated.resize(solver->nVars(), 0);
    propValue.resize(solver->nVars(), 0);

    //If failed var searching is going good, do successively more and more of it
    if ((double)lastTimeZeroDepthAssings > (double)solver->getNumFreeVars() * 0.10)
        numPropsMultiplier = std::max(numPropsMultiplier*1.3, 1.6);
    else
        numPropsMultiplier = 1.0;
    numPropsTodo = (uint64_t) ((double)numPropsTodo * numPropsMultiplier * solver->conf.probeMultiplier);
    numPropsTodo = (double)numPropsTodo * std::pow(numCalls, 0.2);

    //Use candidates
    sortAndResetCandidates();
    candidates.clear();

    //Calculate the set of possible variables for branching on randomly
    vector<Var> possCh;
    for(size_t i = 0; i < solver->nVars(); i++) {
        if (solver->value(i) == l_Undef
            && solver->decisionVar[i]
        ) {
            possCh.push_back(i);
        }
    }

    //Random swap
    for (size_t i = 0
        //Seems redundant, but '-1' on unsigned wraps around
        ; i < possCh.size() && i < possCh.size()-1
        ; i++
    ) {
        std::swap(
            possCh[i]
            , possCh[i+solver->mtrand.randInt(possCh.size()-1-i)]
        );
    }

    //For fast black-listing, O(1)-time lookup
    vector<size_t> lookup(solver->nVars(), std::numeric_limits<size_t>::max());
    for (size_t i = 0; i < possCh.size(); i++) {
        lookup[possCh[i]] = i;
    }

    const uint64_t origBogoProps = solver->propStats.bogoProps;
    for(size_t i = 0
        ; i < possCh.size()
            && solver->propStats.bogoProps + extraTime < origBogoProps + numPropsTodo
        ; i++
    ) {
        runStats.numLoopIters++;
        const Var var = possCh[i];

        //Check if already blacklisted
        if (var == std::numeric_limits<Var>::max())
            continue;

        Lit lit = Lit(var, false);

        extraTime += 200;

        //Check if var is set already
        if (solver->value(lit.var()) != l_Undef
            || !solver->decisionVar[lit.var()]
            || visitedAlready[lit.toInt()]
        ) {
            continue;
        }

        //If this lit is reachable from somewhere else, then reach it from there
        if (solver->timestamp[lit.toInt()].dominator[STAMP_IRRED] != lit_Undef) {
            const Lit betterlit = solver->timestamp[lit.toInt()].dominator[STAMP_IRRED];
            if (solver->value(betterlit.var()) == l_Undef
                && solver->decisionVar[betterlit.var()]
            ) {
                //Update lit
                lit = betterlit;

                //Blacklist new lit
                possCh[lookup[lit.var()]] = std::numeric_limits<Var>::max();

                //Must not have visited it already, otherwise the stamp dominator would be incorrect
                assert(!visitedAlready[lit.toInt()]);
            }
        }

        //Update stats
        runStats.numVarProbed++;

        //Try it
        if (!tryThis(lit, true))
            goto end;

        //If we are still unset, do the opposite, too
        //this lets us carry out BothProp
        if (solver->value(lit) == l_Undef
            && !tryThis((~lit), false)
        ) {
            goto end;
        }
    }

end:

    runStats.zeroDepthAssigns = solver->trail.size() - origTrailSize;
    if (solver->ok && runStats.zeroDepthAssigns) {
        double time = cpuTime();
        bool advancedCleanup = false;
        //If more than 10% were set, detach&reattach. It's faster
        if ((double)runStats.origNumFreeVars - (double)solver->getNumFreeVars()
                >  (double)runStats.origNumFreeVars/10.0
            && solver->getNumLongClauses() > 200000
        ) {
            //Advanced cleanup
            if (solver->conf.verbosity >= 5)
                cout << "c Advanced cleanup after probing" << endl;
            advancedCleanup = true;
            CompleteDetachReatacher reattacher(solver);
            reattacher.detachNonBinsNonTris();
            const bool ret = reattacher.reattachLongs();
            release_assert(ret == true);
        } else {
            //Standard cleanup
            if (solver->conf.verbosity >= 5)
                cout << "c Standard cleanup after probing" << endl;
            solver->clauseCleaner->removeAndCleanAll();
        }

        //Tell me about the speed of cleanup
        if (solver->conf.verbosity  >= 1 &&
            (runStats.zeroDepthAssigns > 100 || advancedCleanup)
        ) {
            cout
            << "c Cleaning up after probing: "
            << std::setw(8) << std::fixed << std::setprecision(2)
            << cpuTime() - time << " s "
            << endl;
        }
    }

    //Update stats
    for(size_t i = 0; i < visitedAlready.size(); i++) {
        if (visitedAlready[i])
            runStats.numVisited++;
    }
    lastTimeZeroDepthAssings = runStats.zeroDepthAssigns;
    runStats.cpu_time = cpuTime() - myTime;
    runStats.propStats = solver->propStats;
    globalStats += runStats;

    //Print & update stats
    if (solver->conf.verbosity >= 1) {
        if (solver->conf.verbosity >= 3)
            runStats.print(solver->nVars());
        else
            runStats.printShort();
    }
    solver->testAllClauseAttach();
    return solver->ok;
}
Beispiel #11
0
bool Prober::tryThis(const Lit lit, const bool first)
{
    //Clean state if this is the 1st of two
    if (first) {
        propagated.removeThese(propagatedBitSet);
        propagatedBitSet.clear();
        bothSame.clear();
    }

    //Start-up cleaning
    runStats.numProbed++;

    //Test removal of non-learnt binary clauses
    #ifdef DEBUG_REMOVE_USELESS_BIN
    fillTestUselessBinRemoval(lit);
    #endif

    solver->newDecisionLevel();
    solver->enqueue(lit);
    solver->varData[lit.var()].depth = 0;

    if (solver->conf.verbosity >= 6)
        cout << "c Probing lit " << lit << endl;

    Lit failed = lit_Undef;
    if (solver->mtrand.randInt(1) == 0) {
        const StampType stampType = solver->mtrand.randInt(1) ? STAMP_IRRED : STAMP_RED;
        failed = solver->propagateFullDFS(stampType);
    } else {
        failed = solver->propagateFullBFS();
    }
    if (failed != lit_Undef) {
        if (solver->conf.verbosity >= 6) {
            cout << "c Failed on lit " << lit << endl;
        }

        solver->cancelZeroLight();

        //Update conflict stats
        runStats.numFailed++;
        runStats.conflStats.update(solver->lastConflictCausedBy);
        runStats.conflStats.numConflicts++;
        runStats.addedBin += solver->hyperBinResAll();
        std::pair<size_t, size_t> tmp = solver->removeUselessBins();
        runStats.removedIrredBin += tmp.first;
        runStats.removedRedBin += tmp.second;

        vector<Lit> lits;
        lits.push_back(~failed);
        solver->addClauseInt(lits, true);

        return solver->ok;
    }

    //Fill bothprop, cache
    assert(solver->decisionLevel() > 0);
    size_t numElemsSet = solver->trail.size() - solver->trail_lim[0];
    for (int64_t c = solver->trail.size()-1; c != (int64_t)solver->trail_lim[0] - 1; c--) {
        const Lit thisLit = solver->trail[c];
        const Var var = thisLit.var();

        //If this is the first, set what is propagated
        if (first) {
            //Visited this var, needs clear later on
            propagatedBitSet.push_back(var);

            //Set prop has been done
            propagated.setBit(var);

            //Set propValue
            if (solver->assigns[var].getBool())
                propValue.setBit(var);
            else
                propValue.clearBit(var);
        } else if (propagated[var]) {
            if (propValue[var] == solver->value(var).getBool()) {
                //they both imply the same
                bothSame.push_back(Lit(var, !propValue[var]));
            }
        }

        visitedAlready[thisLit.toInt()] = 1;

        //Update cache, if the trail was within limits (cacheUpdateCutoff)
        const Lit ancestor = solver->varData[thisLit.var()].reason.getAncestor();
        if (solver->conf.doCache
            && thisLit != lit
            && numElemsSet <= solver->conf.cacheUpdateCutoff
            //&& cacheUpdated[(~ancestor).toInt()] == 0
        ) {
            //Update stats/markings
            //cacheUpdated[(~ancestor).toInt()]++;
            extraTime += 1;
            extraTime += solver->implCache[(~ancestor).toInt()].lits.size()/100;
            extraTime += solver->implCache[(~thisLit).toInt()].lits.size()/100;

            const bool learntStep = solver->varData[thisLit.var()].reason.getLearntStep();

            //Update the cache now
            assert(ancestor != lit_Undef);
            solver->implCache[(~ancestor).toInt()].merge(
                solver->implCache[(~thisLit).toInt()].lits
                , thisLit
                , learntStep
                , ancestor
                , solver->seen
            );

            #ifdef VERBOSE_DEBUG_FULLPROP
            cout << "The impl cache of " << (~ancestor) << " is now: ";
            cout << solver->implCache[(~ancestor).toInt()] << endl;
            #endif
        }
    }

    solver->cancelZeroLight();
    runStats.addedBin += solver->hyperBinResAll();
    std::pair<size_t, size_t> tmp = solver->removeUselessBins();
    runStats.removedIrredBin += tmp.first;
    runStats.removedRedBin += tmp.second;
    #ifdef DEBUG_REMOVE_USELESS_BIN
    testBinRemoval(lit);
    #endif

    if (!first) {
        //Add bothsame
        for(size_t i = 0; i < bothSame.size(); i++) {
            extraTime += 3;
            solver->enqueue(bothSame[i]);
        }
        runStats.bothSameAdded += bothSame.size();
    }
    assert(solver->ok);
    solver->ok = solver->propagate().isNULL();

    return solver->ok;
}
Beispiel #12
0
 inline Pass::Pass(const Lit x) {
   pa = std::map<Var, bool>();
   pa[x.var()] = x.val();
 }
Beispiel #13
0
bool Prober::try_this(const Lit lit, const bool first)
{
    //Clean state if this is the 1st of two
    if (first) {
        clear_up_before_first_set();
    }
    toEnqueue.clear();
    runStats.numProbed++;
    solver->new_decision_level();
    solver->enqueue(lit);
    solver->depth[lit.var()] = 0;
    if (solver->conf.verbosity >= 6) {
        cout
        << "c Probing lit " << lit
        << endl;
    }

    Lit failed = lit_Undef;
    if (!propagate(failed)) {
        return solver->okay();
    }

    if (failed == lit_Undef) {
        if (solver->conf.verbosity >= 6)
            cout << "c Did not fail on lit " << lit << endl;

        //Fill bothprop, cache
        assert(solver->decisionLevel() > 0);
        size_t numElemsSet = solver->trail_size() - solver->trail_lim[0];
        for (int64_t c = solver->trail_size()-1
            ; c != (int64_t)solver->trail_lim[0] - 1
            ; c--
        ) {
            extraTime += 2;
            const Lit thisLit = solver->trail[c];
            const uint32_t var = thisLit.var();

            if (solver->conf.doBothProp) {
                check_and_set_both_prop(var, first);
            }
            visitedAlready[thisLit.toInt()] = 1;
            if (solver->conf.otfHyperbin) {
                update_cache(thisLit, lit, numElemsSet);
            }
        }

        if (!solver->conf.otfHyperbin
            && solver->conf.doCache
        ) {
            add_rest_of_lits_to_cache(lit);
        }
    }

    solver->cancelUntil<false>(0);
    solver->add_otf_subsume_long_clauses();
    solver->add_otf_subsume_implicit_clause();
    runStats.addedBin += solver->hyper_bin_res_all();
    std::pair<size_t, size_t> tmp = solver->remove_useless_bins();
    runStats.removedIrredBin += tmp.first;
    runStats.removedRedBin += tmp.second;

    if (failed != lit_Undef) {
        if (solver->conf.verbosity >= 6) {
            cout << "c Failed while enq + prop " << lit
            << " Lit that got propagated to both values: " << failed << endl;
        }
        runStats.numFailed++;
        #ifdef STATS_NEEDED
        runStats.conflStats.update(solver->lastConflictCausedBy);
        #endif
        runStats.conflStats.numConflicts++;

        vector<Lit> lits;
        lits.push_back(~failed);
        solver->add_clause_int(lits, true);
        clear_up_before_first_set();
        return solver->ok;
    } else {
        assert(solver->ok);
        runStats.bothSameAdded += toEnqueue.size();
        extraTime += 3*toEnqueue.size();
        return solver->fully_enqueue_these(toEnqueue);
    }
}
Beispiel #14
0
bool Prober::probe(vector<uint32_t>* probe_order)
{
    assert(solver->decisionLevel() == 0);
    assert(solver->nVars() > 0);
    solver->test_all_clause_attached();

    clean_clauses_before_probe();
    reset_stats_and_state();
    uint64_t numPropsTodo = calc_numpropstodo();

    const double myTime = cpuTime();
    const size_t origTrailSize = solver->trail_size();
    numPropsTodo = update_numpropstodo_based_on_prev_performance(numPropsTodo);

    if (probe_order == NULL) {
        randomize_possible_choices();
    } else {
        vars_to_probe = *probe_order;
    }

    if (solver->conf.verbosity >= 10) {
        cout << "Order of probe:";
        for(auto x: vars_to_probe) {
            cout << x+1 << ", ";
        }
        cout << endl;
    }

    assert(solver->propStats.bogoProps == 0);
    assert(solver->propStats.otfHyperTime == 0);
    single_prop_tout = (double)numPropsTodo *solver->conf.single_probe_time_limit_perc;

    for(size_t i = 0
        ; i < vars_to_probe.size()
        && limit_used() < numPropsTodo
        && !solver->must_interrupt_asap()
        ; i++
    ) {
        if ((i & 0xff) == 0xff
            && cpuTime() >= solver->conf.maxTime
        ) {
            break;
        }
        extraTime += 20;
        runStats.numLoopIters++;
        const uint32_t var = vars_to_probe[i];

        //Probe 'false' first --> this is not critical
        Lit lit = Lit(var, false);

        //Check if var is set already
        if (solver->value(lit.var()) != l_Undef
            || solver->varData[lit.var()].removed != Removed::none
            || visitedAlready[lit.toInt()]
        ) {
            continue;
        }

        runStats.numVarProbed++;
        extraTime += 20;

        if (!try_this(lit, true))
            goto end;

        if (solver->value(lit) == l_Undef
            && !try_this(~lit, false)
        ) {
            goto end;
        }
    }

end:

    if (solver->conf.verbosity >= 10) {
        cout << "c main loop for " << __PRETTY_FUNCTION__
        << " finished: "
        << " must_interrupt? " << solver->must_interrupt_asap()
        << " limit_used? " << (limit_used() >= numPropsTodo)
        << endl;
    }

    //Delete any remaining binaries to add or remove
    //next time, variables will be renumbered/etc. so it will be wrong
    //to add/remove them
    solver->needToAddBinClause.clear();
    solver->uselessBin.clear();

    runStats.zeroDepthAssigns = solver->trail_size() - origTrailSize;
    if (solver->ok && runStats.zeroDepthAssigns) {
        clean_clauses_after_probe();
    }

    update_and_print_stats(myTime, numPropsTodo);
    check_if_must_disable_otf_hyperbin_and_tred(numPropsTodo);
    check_if_must_disable_cache_update();

    solver->test_all_clause_attached();
    return solver->ok;
}
Beispiel #15
0
Base*
Ran::mutating_canonicalize()
{
    Base* ret = this;
    switch (m_subs.size()) {
    case 2: {
        auto it = begin(m_subs);
        Lit* subA = dynamic_cast<Lit*>(*it); it++;
        Lit* subB = dynamic_cast<Lit*>(*it);
        // TODO: Generalize to n bytes and reuse auto_set_detected_pmatch()
        if (subA and subB) {    // if both literals
            const auto nbytes = subA->bitsize().get() / 8;
            if ((subA->bitsize() == 8 and
                 subB->bitsize() == 8 and
                 subA->get_byte() == 0 and
                 (~subB->get_byte()) == 0)
                or
                (subA->bitsize() == 16 and
                 subB->bitsize() == 16 and
                 subA->get_i16ne() == 0 and
                 (~subB->get_i16ne()) == 0)
                or
                (subA->bitsize() == 32 and
                 subB->bitsize() == 32 and
                 subA->get_i32ne() == 0 and
                 (~subB->get_i32ne()) == 0)
                or
                (subA->bitsize() == 64 and
                 subB->bitsize() == 64 and
                 subA->get_i64ne() == 0 and
                 (~subB->get_i64ne()) == 0))
            {
                ret = mutate_to(anybytes(nbytes)); // mutate \p this to \c Any
            }
        }
        break;
    }
    default: {
        break;
    }
    }
    return ret;
}
void SubsumeImplicit::try_subsume_tri(
    const Lit lit
    , Watched*& i
    , Watched*& j
    , const bool doStamp
) {
    //Only treat one of the TRI's instances
    if (lit > i->lit2()) {
        *j++ = *i;
        return;
    }

    bool remove = false;

    //Subsumed by bin
    if (lastLit2 == i->lit2()
        && lastLit3 == lit_Undef
    ) {
        if (lastRed && !i->red()) {
            assert(lastBin->isBin());
            assert(lastBin->red());
            assert(lastBin->lit2() == lastLit2);

            lastBin->setRed(false);
            timeAvailable -= 20;
            timeAvailable -= solver->watches[lastLit2.toInt()].size();
            findWatchedOfBin(solver->watches, lastLit2, lit, true).setRed(false);
            solver->binTri.redBins--;
            solver->binTri.irredBins++;
            lastRed = false;
        }

        remove = true;
    }

    //Subsumed by Tri
    if (!remove
        && lastLit2 == i->lit2()
        && lastLit3 == i->lit3()
    ) {
        //The sorting algorithm prefers irred to red, so it is
        //impossible to have irred before red
        assert(!(i->red() == false && lastRed == true));

        remove = true;
    }

    tmplits.clear();
    tmplits.push_back(lit);
    tmplits.push_back(i->lit2());
    tmplits.push_back(i->lit3());

    //Subsumed by stamp
    if (doStamp && !remove
        && (solver->conf.otfHyperbin || !solver->drup->enabled())
    ) {
        timeAvailable -= 15;
        remove = solver->stamp.stampBasedClRem(tmplits);
        runStats.stampTriRem += remove;
    }

    //Subsumed by cache
    if (!remove
        && solver->conf.doCache
        && (solver->conf.otfHyperbin || !solver->drup->enabled())
    ) {
        for(size_t at = 0; at < tmplits.size() && !remove; at++) {
            timeAvailable -= (int64_t)solver->implCache[lit.toInt()].lits.size();
            for (vector<LitExtra>::const_iterator
                it2 = solver->implCache[tmplits[at].toInt()].lits.begin()
                , end2 = solver->implCache[tmplits[at].toInt()].lits.end()
                ; it2 != end2
                ; it2++
            ) {
                if ((   it2->getLit() == tmplits[0]
                        || it2->getLit() == tmplits[1]
                        || it2->getLit() == tmplits[2]
                    )
                    && it2->getOnlyIrredBin()
                ) {
                    remove = true;
                    runStats.cacheTriRem++;
                    break;
                 }
            }
        }
    }

    if (remove) {
        timeAvailable -= 30;
        solver->remove_tri_but_lit1(lit, i->lit2(), i->lit3(), i->red(), timeAvailable);
        runStats.remTris++;
        (*solver->drup) << del << lit  << i->lit2()  << i->lit3() << fin;
        return;
    }

    //Don't remove
    lastLit2 = i->lit2();
    lastLit3 = i->lit3();
    lastRed = i->red();

    *j++ = *i;
    return;
}
Beispiel #17
0
bool DataSync::shareUnitData()
{
    uint32_t thisGotUnitData = 0;
    uint32_t thisSentUnitData = 0;

    SharedData& shared = *sharedData;
    if (shared.value.size() < solver->nVarsOutside()) {
        shared.value.resize(solver->nVarsOutside(), l_Undef);
    }
    for (uint32_t var = 0; var < solver->nVarsOutside(); var++) {
        Lit thisLit = Lit(var, false);
        thisLit = solver->map_to_with_bva(thisLit);
        thisLit = solver->varReplacer->get_lit_replaced_with_outer(thisLit);
        thisLit = solver->map_outer_to_inter(thisLit);
        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->varData[litToEnqueue.var()].removed != Removed::none) {
                continue;
            }

            solver->enqueue(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)
    ) {
        cout
        << "c [sync] got units " << thisGotUnitData
        << " sent units " << thisSentUnitData
        << endl;
    }

    stats.recvUnitData += thisGotUnitData;
    stats.sentUnitData += thisSentUnitData;

    return true;
}
Beispiel #18
0
bool ImplCache::clean(Solver* solver, bool* setSomething)
{
    assert(solver->ok);
    assert(solver->decisionLevel() == 0);
    vector<Lit> toEnqueue;

    double myTime = cpuTime();
    uint64_t numUpdated = 0;
    uint64_t numCleaned = 0;
    uint64_t numFreed = 0;

    //Merge in & free memory
    for (Var var = 0; var < solver->nVars(); var++) {

        //If replaced, merge it into the one that replaced it
        if (solver->varData[var].removed == Removed::replaced) {
            for(int i = 0; i < 2; i++) {
                const Lit litOrig = Lit(var, i);
                if (implCache[litOrig.toInt()].lits.empty())
                    continue;

                const Lit lit = solver->varReplacer->getLitReplacedWith(litOrig);

                //Updated literal must be normal, otherwise, biig problems e.g
                //implCache is not even large enough, etc.
                if (solver->varData[lit.var()].removed == Removed::none) {
                    bool taut = implCache.at(lit.toInt()).merge(
                        implCache[litOrig.toInt()].lits
                        , lit_Undef //nothing to add
                        , false //replaced, so 'irred'
                        , lit.var() //exclude the literal itself
                        , solver->seen
                    );

                    if (taut) {
                        toEnqueue.push_back(lit);
                        (*solver->drup) << lit << fin;
                    }
                }
            }
        }

        //Free it
        if (solver->value(var) != l_Undef
            || solver->varData[var].removed == Removed::elimed
            || solver->varData[var].removed == Removed::replaced
            || solver->varData[var].removed == Removed::decomposed
        ) {
            vector<LitExtra> tmp1;
            numFreed += implCache[Lit(var, false).toInt()].lits.capacity();
            implCache[Lit(var, false).toInt()].lits.swap(tmp1);

            vector<LitExtra> tmp2;
            numFreed += implCache[Lit(var, true).toInt()].lits.capacity();
            implCache[Lit(var, true).toInt()].lits.swap(tmp2);
        }
    }

    vector<uint16_t>& inside = solver->seen;
    vector<uint16_t>& irred = solver->seen2;
    size_t wsLit = 0;
    for(vector<TransCache>::iterator
        trans = implCache.begin(), transEnd = implCache.end()
        ; trans != transEnd
        ; trans++, wsLit++
    ) {
        //Stats
        size_t origSize = trans->lits.size();
        size_t newSize = 0;

        //Update to replaced vars, remove vars already set or eliminated
        Lit vertLit = Lit::toLit(wsLit);
        vector<LitExtra>::iterator it = trans->lits.begin();
        vector<LitExtra>::iterator it2 = it;
        for (vector<LitExtra>::iterator end = trans->lits.end(); it != end; it++) {
            Lit lit = it->getLit();
            assert(lit.var() != vertLit.var());

            //Remove if value is set
            if (solver->value(lit.var()) != l_Undef)
                continue;

            //Update to its replaced version
            if (solver->varData[lit.var()].removed == Removed::replaced
                || solver->varData[lit.var()].removed == Removed::queued_replacer
            ) {
                lit = solver->varReplacer->getLitReplacedWith(lit);

                //This would be tautological (and incorrect), so skip
                if (lit.var() == vertLit.var())
                    continue;
                numUpdated++;
            }

            //Yes, it's possible that the child was not set, but the parent is set
            //This is because there is a delay between replacement and cache cleaning
            if (solver->value(lit.var()) != l_Undef)
                continue;

            //If updated version is eliminated/decomposed, skip
            if (solver->varData[lit.var()].removed != Removed::none)
                continue;

            //Mark irred
            irred[lit.toInt()] |= (char)it->getOnlyIrredBin();

            //If we have already visited this var, just skip over, but update irred
            if (inside[lit.toInt()]) {
                continue;
            }

            inside[lit.toInt()] = true;
            *it2++ = LitExtra(lit, it->getOnlyIrredBin());
            newSize++;
        }
        trans->lits.resize(newSize);

        //Now that we have gone through the list, go through once more to:
        //1) set irred right (above we might have it set later)
        //2) clear 'inside'
        //3) clear 'irred'
        for (vector<LitExtra>::iterator it = trans->lits.begin(), end = trans->lits.end(); it != end; it++) {
            Lit lit = it->getLit();

            //Clear 'inside'
            inside[lit.toInt()] = false;

            //Clear 'irred'
            const bool nRed = irred[lit.toInt()];
            irred[lit.toInt()] = false;

            //Set non-leartness correctly
            *it = LitExtra(lit, nRed);
            assert(solver->varData[it->getLit().var()].removed == Removed::none);
            assert(solver->value(it->getLit()) == l_Undef);
        }
        numCleaned += origSize-trans->lits.size();
    }

    size_t origTrailDepth = solver->trail.size();
    solver->enqueueThese(toEnqueue);
    if (setSomething) {
        *setSomething = (solver->trail.size() != origTrailDepth);
    }

    if (solver->conf.verbosity >= 1) {
        cout << "c Cache cleaned."
        << " Updated: " << std::setw(7) << numUpdated/1000 << " K"
        << " Cleaned: " << std::setw(7) << numCleaned/1000 << " K"
        << " Freed: " << std::setw(7) << numFreed/1000 << " K"
        << " T: " << std::setprecision(2) << std::fixed  << (cpuTime()-myTime) << endl;
    }

    return solver->okay();
}
Beispiel #19
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 #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
 inline Var var(const Lit x) {
   return x.var();
 }
Beispiel #22
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 #23
0
bool BVA::bounded_var_addition()
{
    bounded_var_elim_time_limit =
        solver->conf.bva_time_limitM*2ULL*400LL *1000LL
        *solver->conf.global_timeout_multiplier;
    bva_verbosity = false;

    assert(solver->ok);
    if (!solver->conf.do_bva)
        return solver->okay();

    if (solver->conf.verbosity >= 3 || bva_verbosity) {
        cout << "c [occ-bva] Running BVA" << endl;
    }

    if (!solver->propagate_occur())
        return false;

    simplifier->limit_to_decrease = &bounded_var_elim_time_limit;
    int64_t limit_orig = *simplifier->limit_to_decrease;
    solver->clauseCleaner->clean_implicit_clauses();
    if (solver->conf.doStrSubImplicit) {
        solver->subsumeImplicit->subsume_implicit(false);
    }

    bva_worked = 0;
    bva_simp_size = 0;
    var_bva_order.clear();
    calc_watch_irred_sizes();
    for(size_t i = 0; i < solver->nVars()*2; i++) {
        const Lit lit = Lit::toLit(i);
        if (solver->value(lit) != l_Undef
            || solver->varData[lit.var()].removed != Removed::none
        ) {
            continue;
        }
        var_bva_order.insert(lit.toInt());
    }

    double my_time = cpuTime();
    while(!var_bva_order.empty()) {
        if (*simplifier->limit_to_decrease < 0
            || bva_worked >= solver->conf.bva_limit_per_call
            || solver->must_interrupt_asap()
        ) {
            break;
        }

        const Lit lit = Lit::toLit(var_bva_order.removeMin());
        if (solver->conf.verbosity >= 5 || bva_verbosity) {
            cout << "c [occ-bva] trying lit " << lit << endl;
        }
        bool ok = try_bva_on_lit(lit);
        if (!ok)
            break;
    }
    solver->bva_changed();

    bool time_out = *simplifier->limit_to_decrease <= 0;
    const double time_used = cpuTime() - my_time;
    double time_remain = float_div(*simplifier->limit_to_decrease ,limit_orig);
    if (solver->conf.verbosity >= 2) {
        cout
        << "c [occ-bva] added: " << bva_worked
        << " simp: " << bva_simp_size
        << " 2lit: " << ((solver->conf.bva_also_twolit_diff
            && (long)solver->sumConflicts() >= solver->conf.bva_extra_lit_and_red_start) ? "Y" : "N")
        << solver->conf.print_times(time_used, time_out, time_remain)
        << endl;
    }
    if (solver->sqlStats) {
        solver->sqlStats->time_passed(
            solver
            , "bva"
            , time_used
            , time_out
            , time_remain
        );
    }

    return solver->okay();
}
Beispiel #24
0
void CompHandler::moveClausesLong(
    vector<ClOffset>& cs
    , SATSolver* newSolver
    , const uint32_t comp
) {
    vector<Lit> tmp;

    vector<ClOffset>::iterator i, j, end;
    for (i = j = cs.begin(), end = cs.end()
        ; i != end
        ; ++i
    ) {
        Clause& cl = *solver->cl_alloc.ptr(*i);

        //Irred, different comp
        if (!cl.red()) {
            if (compFinder->getVarComp(cl[0].var()) != comp) {
                //different comp, move along
                *j++ = *i;
                continue;
            }
        }

        if (cl.red()) {
            //Check which comp(s) it belongs to
            bool thisComp = false;
            bool otherComp = false;
            for (Lit* l = cl.begin(), *end2 = cl.end(); l != end2; ++l) {
                if (compFinder->getVarComp(l->var()) == comp)
                    thisComp = true;

                if (compFinder->getVarComp(l->var()) != comp)
                    otherComp = true;
            }

            //In both comps, remove it
            if (thisComp && otherComp) {
                solver->detachClause(cl);
                solver->cl_alloc.clauseFree(&cl);
                continue;
            }

            //In one comp, but not this one
            if (!thisComp) {
                //different comp, move along
                *j++ = *i;
                continue;
            }
            assert(thisComp && !otherComp);
        }

        //Let's move it to the other solver!
        #ifdef VERBOSE_DEBUG
        cout << "clause in this comp:" << cl << endl;
        #endif

        //Create temporary space 'tmp' and copy to backup
        tmp.resize(cl.size());
        for (size_t i2 = 0; i2 < cl.size(); ++i2) {
            tmp[i2] = upd_bigsolver_to_smallsolver(cl[i2]);
        }

        //Add 'tmp' to the new solver
        if (cl.red()) {
            #ifdef STATS_NEEDED
            cl.stats.introduced_at_conflict = 0;
            #endif
            //newSolver->addRedClause(tmp, cl.stats);
        } else {
            saveClause(cl);
            newSolver->add_clause(tmp);
        }

        //Remove from here
        solver->detachClause(cl);
        solver->cl_alloc.clauseFree(&cl);
    }
    cs.resize(cs.size() - (i-j));
}
Lit HyperEngine::prop_irred_bin_dfs(
    StampType stampType
    , PropBy& confl
    , const Lit //root
    , bool& restart
) {
    const Lit p = toPropBin.top();
    watch_subarray_const ws = watches[~p];
    size_t done = 0;
    for(const Watched *k = ws.begin(), *end = ws.end()
        ; k != end
        ; k++, done++
    ) {
        propStats.bogoProps += 1;
        //Pre-fetch long clause
        if (k->isClause()) {
            if (value(k->getBlockedLit()) != l_True) {
                const ClOffset offset = k->get_offset();
                __builtin_prefetch(cl_alloc.ptr(offset));
            }

            continue;
        } //end CLAUSE

        //If something other than binary, skip
        if (!k->isBin())
            continue;

        //If stamping only irred, go over red binaries
        if (stampType == STAMP_IRRED
            && k->red()
        ) {
            continue;
        }

        PropResult ret = prop_bin_with_ancestor_info(p, k, confl);
        switch(ret) {
            case PROP_FAIL:
                close_all_timestamps(stampType);
                return analyzeFail(confl);

            case PROP_SOMETHING:
                propStats.bogoProps += 8;
                stamp.stampingTime++;
                stamp.tstamp[trail.back().toInt()].start[stampType] = stamp.stampingTime;
                #ifdef DEBUG_STAMPING
                cout
                << "From " << p << " enqueued " << trail.back()
                << " for stamp.stampingTime " << stamp.stampingTime
                << endl;
                #endif

                toPropNorm.push(trail.back());
                toPropBin.push(trail.back());
                if (stampType == STAMP_IRRED) toPropRedBin.push(trail.back());
                propStats.bogoProps += done*4;
                restart = true;
                return lit_Undef;

            case PROP_NOTHING:
                break;
            default:
                assert(false);
                break;
        }
    }

    //Finished with this literal
    propStats.bogoProps += ws.size()*4;
    toPropBin.pop();
    stamp.stampingTime++;
    stamp.tstamp[p.toInt()].end[stampType] = stamp.stampingTime;
    #ifdef DEBUG_STAMPING
    cout
    << "End time for " << p
    << " is " << stamp.stampingTime
    << endl;
    #endif

    return lit_Undef;
}
Beispiel #26
0
void CompHandler::move_tri_clause(
    SATSolver* newSolver
    , const uint32_t comp
    ,  Watched *i
    , const Lit lit
) {
    const Lit lit2 = i->lit2();
    const Lit lit3 = i->lit3();

    //Unless redundant, cannot be in 2 comps at once
    assert((compFinder->getVarComp(lit.var()) == comp
                && compFinder->getVarComp(lit2.var()) == comp
                && compFinder->getVarComp(lit3.var()) == comp
           ) || i->red()
    );

    //If it's redundant and the lits are in different comps, remove it.
    if (compFinder->getVarComp(lit.var()) != comp
        || compFinder->getVarComp(lit2.var()) != comp
        || compFinder->getVarComp(lit3.var()) != comp
    ) {
        assert(i->red());

        //The way we go through this, it's definitely going to be
        //either lit2 or lit3, not lit, that's in the other comp
        assert(compFinder->getVarComp(lit2.var()) != comp
            || compFinder->getVarComp(lit3.var()) != comp
        );

        remove_tri_except_for_lit1(lit, lit2, lit3);
        return;
    }

    //don't add the same clause twice
    if (lit < lit2
        && lit2 < lit3
    ) {

        //Add clause
        tmp_lits = {upd_bigsolver_to_smallsolver(lit)
            , upd_bigsolver_to_smallsolver(lit2)
            , upd_bigsolver_to_smallsolver(lit3)
        };
        assert(compFinder->getVarComp(lit.var()) == comp);
        assert(compFinder->getVarComp(lit2.var()) == comp);
        assert(compFinder->getVarComp(lit3.var()) == comp);

        //Add new clause
        if (i->red()) {
            //newSolver->addRedClause(tmp_lits);
            numRemovedThirdRed++;
        } else {
            //Save backup
            saveClause(vector<Lit>{lit, lit2, lit3});

            newSolver->add_clause(tmp_lits);
            numRemovedThirdIrred++;
        }
    } else {

        //Just remove, already added above
        if (i->red()) {
            numRemovedThirdRed++;
        } else {
            numRemovedThirdIrred++;
        }
    }
}
Lit HyperEngine::propagate_dfs(
    const StampType stampType
    , const uint64_t timeout
) {
    timedOutPropagateFull = false;
    propStats.otfHyperPropCalled++;
    #ifdef VERBOSE_DEBUG_FULLPROP
    cout << "Prop full started" << endl;
    #endif

    PropBy confl;

    //Assert startup: only 1 enqueued, uselessBin is empty
    assert(uselessBin.empty());
    assert(decisionLevel() == 1);

    //The toplevel decision has to be set specifically
    //If we came here as part of a backtrack to decision level 1, then
    //this is already set, and there is no need to set it
    if (trail.size() - trail_lim.back() == 1) {
        //Set up root node
        Lit root = trail[qhead];
        varData[root.var()].reason = PropBy(~lit_Undef, false, false, false);
    }

    //Set up stacks
    toPropBin.clear();
    toPropRedBin.clear();
    toPropNorm.clear();

    Lit root = trail.back();
    toPropBin.push(root);
    toPropNorm.push(root);
    if (stampType == STAMP_RED)
        toPropRedBin.push(root);

    //Setup
    needToAddBinClause.clear();
    stamp.stampingTime++;
    stamp.tstamp[root.toInt()].start[stampType] = stamp.stampingTime;

    #ifdef DEBUG_STAMPING
    cout
    << "Top-enqueued << " << trail.back()
    << " for stamp.stampingTime " << stamp.stampingTime
    << endl;
    #endif

    while(true) {
        propStats.bogoProps += 3;
        if (need_early_abort_dfs(stampType, timeout))
            return lit_Undef;

        //Propagate binary irred
        bool restart = false;
        while (!toPropBin.empty()) {
            Lit ret = prop_irred_bin_dfs(stampType, confl, root, restart);
            if (ret != lit_Undef)
                return ret;
            if (restart)
                break;
        }
        if (restart)
            continue;

        if (stampType == STAMP_IRRED) {
            while (!toPropRedBin.empty()) {
                Lit ret = prop_red_bin_dfs(stampType, confl, root, restart);
                if (ret != lit_Undef)
                    return ret;
                if (restart)
                    break;
            }
        }
        if (restart)
            continue;

        while (!toPropNorm.empty()) {
            Lit ret = prop_larger_than_bin_cl_dfs(stampType, confl, root, restart);
            if (ret != lit_Undef)
                return ret;
            if (restart)
                break;

            qhead++;
        }
        if (restart)
            continue;

        //Nothing more to propagate
        break;
    }

    return lit_Undef;
}
Beispiel #28
0
void CompHandler::moveClausesImplicit(
    SATSolver* newSolver
    , const uint32_t comp
    , const vector<Var>& vars
) {
    numRemovedHalfIrred = 0;
    numRemovedHalfRed = 0;
    numRemovedThirdIrred = 0;
    numRemovedThirdRed = 0;

    for(const Var var: vars) {
    for(unsigned sign = 0; sign < 2; ++sign) {
        const Lit lit = Lit(var, sign);
        watch_subarray ws = solver->watches[lit.toInt()];

        //If empty, nothing to to, skip
        if (ws.empty()) {
            continue;
        }

        Watched *i = ws.begin();
        Watched *j = i;
        for (Watched *end2 = ws.end()
            ; i != end2
            ; ++i
        ) {
            //At least one variable inside comp
            if (i->isBinary()
                && (compFinder->getVarComp(lit.var()) == comp
                    || compFinder->getVarComp(i->lit2().var()) == comp
                )
            ) {
                move_binary_clause(newSolver, comp, i, lit);
                continue;
            }

            if (i->isTri()
                && (compFinder->getVarComp(lit.var()) == comp
                    || compFinder->getVarComp(i->lit2().var()) == comp
                    || compFinder->getVarComp(i->lit3().var()) == comp
                )
            ) {
                move_tri_clause(newSolver, comp, i, lit);
                continue;
            }

            *j++ = *i;
        }
        ws.shrink_(i-j);
    }}

    assert(numRemovedHalfIrred % 2 == 0);
    solver->binTri.irredBins -= numRemovedHalfIrred/2;

    assert(numRemovedThirdIrred % 3 == 0);
    solver->binTri.irredTris -= numRemovedThirdIrred/3;

    assert(numRemovedHalfRed % 2 == 0);
    solver->binTri.redBins -= numRemovedHalfRed/2;

    assert(numRemovedThirdRed % 3 == 0);
    solver->binTri.redTris -= numRemovedThirdRed/3;
}
/**
hop backwards from thisAncestor until:
1) we reach ancestor of 'conflict' -- at this point, we return TRUE
2) we reach an invalid point. Either root, or an invalid hop. We return FALSE.
*/
bool HyperEngine::is_ancestor_of(
    const Lit conflict
    , Lit thisAncestor
    , const bool thisStepRed
    , const bool onlyIrred
    , const Lit lookingForAncestor
) {
    propStats.otfHyperTime += 1;
    #ifdef VERBOSE_DEBUG_FULLPROP
    cout << "is_ancestor_of."
    << "conflict: " << conflict
    << " thisAncestor: " << thisAncestor
    << " thisStepRed: " << thisStepRed
    << " onlyIrred: " << onlyIrred
    << " lookingForAncestor: " << lookingForAncestor << endl;
    #endif

    //Was propagated at level 0 -- clauseCleaner will remove the clause
    if (lookingForAncestor == lit_Undef)
        return false;

    if (lookingForAncestor == thisAncestor) {
        #ifdef VERBOSE_DEBUG_FULLPROP
        cout << "Last position inside prop queue is not saved during propFull" << endl
        << "This may be the same exact binary clause -- not removing" << endl;
        #endif
        return false;
    }

    #ifdef VERBOSE_DEBUG_FULLPROP
    cout << "Looking for ancestor of " << conflict << " : " << lookingForAncestor << endl;
    cout << "This step based on redundant cl? " << (thisStepRed ? "yes" : "false") << endl;
    cout << "Only irred is acceptable?" << (onlyIrred ? "yes" : "no") << endl;
    cout << "This step would be based on redundant cl?" << (thisStepRed ? "yes" : "no") << endl;
    #endif

    if (onlyIrred && thisStepRed) {
        #ifdef VERBOSE_DEBUG_FULLPROP
        cout << "This step doesn't work -- is redundant but needs irred" << endl;
        #endif
        return false;
    }

    //This is as low as we should search -- we cannot find what we are searchig for lower than this
    const size_t bottom = depth[lookingForAncestor.var()];

    while(thisAncestor != lit_Undef
        && (!use_depth_trick || bottom <= depth[thisAncestor.var()])
    ) {
        #ifdef VERBOSE_DEBUG_FULLPROP
        cout << "Current acestor: " << thisAncestor
        << " redundant step? " << varData[thisAncestor.var()].reason.isRedStep()
        << endl;
        #endif

        if (thisAncestor == conflict) {
            #ifdef VERBOSE_DEBUG_FULLPROP
            cout << "We are trying to step over the conflict."
            << " That would create a loop." << endl;
            #endif
            return false;
        }

        if (thisAncestor == lookingForAncestor) {
            #ifdef VERBOSE_DEBUG_FULLPROP
            cout << "Ancestor found" << endl;
            #endif
            return true;
        }

        const PropBy& data = varData[thisAncestor.var()].reason;
        if ((onlyIrred && data.isRedStep())
            || data.getHyperbinNotAdded()
        ) {
            #ifdef VERBOSE_DEBUG_FULLPROP
            cout << "Wrong kind of hop would be needed" << endl;
            #endif
            return false;  //reached would-be redundant hop (but this is irred)
        }

        thisAncestor = data.getAncestor();
        propStats.otfHyperTime += 1;
    }

    #ifdef VERBOSE_DEBUG_FULLPROP
    cout << "Exit, reached root" << endl;
    #endif

    return false;
}
Beispiel #30
0
Lit CNF_Manager::translateExprRec(const Expr& e, CNF_Formula& cnf, const Theorem& thmIn)
{
  if (e.isFalse()) return Lit::getFalse();
  if (e.isTrue()) return Lit::getTrue();
  if (e.isNot()) return !translateExprRec(e[0], cnf, thmIn);

  ExprHashMap<Var>::iterator iMap = d_cnfVars.find(e);

  if (e.isTranslated()) {
    DebugAssert(iMap != d_cnfVars.end(), "Translated expr should be in map");
    return Lit((*iMap).second);
  }
  else e.setTranslated(d_bottomScope);

  Var v(int(d_varInfo.size()));
  bool translateOnly = false;

  if (iMap != d_cnfVars.end()) {
    v = (*iMap).second;
    translateOnly = true;
    d_varInfo[v].fanouts.clear();
  }
  else {
    d_varInfo.resize(v+1);
    d_varInfo.back().expr = e;
    d_cnfVars[e] = v;
  }

  Expr::iterator i, iend;
  bool isAnd = false;
  switch (e.getKind()) {
    case AND:
      isAnd = true;
    case OR: {
      vector<Lit> lits;
      unsigned idx;
      for (i = e.begin(), iend = e.end(); i != iend; ++i) {
        lits.push_back(translateExprRec(*i, cnf, thmIn));
      }

      //      DebugAssert(concreteExpr(e,Lit(v)) == e,"why here");

      for (idx = 0; idx < lits.size(); ++idx) {
        cnf.newClause();
        cnf.addLiteral(Lit(v),isAnd);
        cnf.addLiteral(lits[idx], !isAnd);
	
	//	DebugAssert(concreteExpr(e[idx],lits[idx]) == e[idx], "why here");

	std::string reasonStr = (isAnd ? "and_mid" : "or_mid");
	Expr after = e[idx] ;
	cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, idx)); // by yeting
      }

      cnf.newClause();
      cnf.addLiteral(Lit(v),!isAnd);
      for (idx = 0; idx < lits.size(); ++idx) {
        cnf.addLiteral(lits[idx], isAnd);
      }

      std::string reasonStr = (isAnd ? "and_final" : "or_final") ;   
      Expr after = e ;

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, 0)); // by yeting
      break;
    }
    case IMPLIES: {
      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 2)); // by yeting

      break;
    }
    case IFF: {
      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 3)); // by yeting
      break;
    }
    case XOR: {

      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);

      //      DebugAssert(concreteExpr(e, Lit(v)) == e, "why here");
      //      DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here");
      //      DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here");


      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 0)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 3)); // by yeting
      break;
    }
    case ITE:
    {

      Lit arg0 = translateExprRec(e[0], cnf, thmIn);
      Lit arg1 = translateExprRec(e[1], cnf, thmIn);
      Lit arg2 = translateExprRec(e[2], cnf, thmIn);


      Expr aftere0 = concreteExpr(e[0], arg0);
      Expr aftere1 = concreteExpr(e[1], arg1);
      Expr aftere2 = concreteExpr(e[2], arg2);
      
      vector<Expr> after ;
      after.push_back(aftere0);
      after.push_back(aftere1);
      after.push_back(aftere2);
      
      Theorem e0thm;
      Theorem e1thm;
      Theorem e2thm;

      { e0thm = d_iteMap[e[0]];
	if (e0thm.isNull()) e0thm = d_commonRules->reflexivityRule(e[0]);
	e1thm = d_iteMap[e[1]];
	if (e1thm.isNull()) e1thm = d_commonRules->reflexivityRule(e[1]);
	e2thm = d_iteMap[e[2]];
	if (e2thm.isNull()) e2thm = d_commonRules->reflexivityRule(e[2]);
      }

      vector<Theorem> thms ;
      thms.push_back(e0thm);
      thms.push_back(e1thm);      
      thms.push_back(e2thm);

 

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg2);
      
      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 1)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0);
      cnf.addLiteral(arg2,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 2)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 3)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg0,true);
      cnf.addLiteral(arg1);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 4)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v));
      cnf.addLiteral(arg1,true);
      cnf.addLiteral(arg2,true);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 5)); // by yeting

      cnf.newClause();
      cnf.addLiteral(Lit(v),true);
      cnf.addLiteral(arg1);
      cnf.addLiteral(arg2);

      cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 6)); // by yeting
      
      break;
    }
    default:
    {
      DebugAssert(!e.isAbsAtomicFormula() || d_varInfo[v].expr == e,
                  "Corrupted Varinfo");
      if (e.isAbsAtomicFormula()) {
        registerAtom(e, thmIn);
        return Lit(v);
      }

      Theorem thm = replaceITErec(e, v, translateOnly);
      const Expr& e2 = thm.getRHS();
      DebugAssert(e2.isAbsAtomicFormula(), "Expected AbsAtomicFormula");
      if (e2.isTranslated()) {
        // Ugly corner case: we happen to create an expression that has been
        // created before.  We remove the current variable and fix up the
        // translation stack.
        if (translateOnly) {
          DebugAssert(v == d_cnfVars[e2], "Expected literal match");
        }
        else {
          d_varInfo.resize(v);
          while (!d_translateQueueVars.empty() &&
                 d_translateQueueVars.back() == v) {
            d_translateQueueVars.pop_back();
          }
          DebugAssert(d_cnfVars.find(e2) != d_cnfVars.end(),
                      "Expected existing literal");
          v = d_cnfVars[e2];
          d_cnfVars[e] = v;
          while (d_translateQueueVars.size() < d_translateQueueThms.size()) {
            d_translateQueueVars.push_back(v);
          }
        }
      }
      else {
        e2.setTranslated(d_bottomScope);
        // Corner case: don't register reflexive equality
        if (!e2.isEq() || e2[0] != e2[1]) registerAtom(e2, thmIn);
        if (!translateOnly) {
          if (d_cnfVars.find(e2) == d_cnfVars.end()) {
            d_varInfo[v].expr = e2;
            d_cnfVars[e2] = v;
          }
          else {
            // Same corner case in an untranslated expr
            d_varInfo.resize(v);
            while (!d_translateQueueVars.empty() &&
                   d_translateQueueVars.back() == v) {
              d_translateQueueVars.pop_back();
            }
            v = d_cnfVars[e2];
            d_cnfVars[e] = v;
            while (d_translateQueueVars.size() < d_translateQueueThms.size()) {
              d_translateQueueVars.push_back(v);
            }
          }
        }
      }
      return Lit(v);
    }
  }

  // Record fanins / fanouts
  Lit l;
  for (i = e.begin(), iend = e.end(); i != iend; ++i) {
    l = getCNFLit(*i);
    DebugAssert(!l.isNull(), "Expected non-null literal");
    if (!translateOnly) d_varInfo[v].fanins.push_back(l);
    if (l.isVar()) d_varInfo[l.getVar()].fanouts.push_back(v);
  }
  return Lit(v);
}