Example #1
0
bool Prober::propagate(Lit& failed)
{
    if (solver->conf.otfHyperbin) {
        //Set timeout for ONE enqueue. This used so that in case ONE enqueue
        //takes too long (usually because of hyper-bin), we exit early
        uint64_t timeout = std::numeric_limits<uint64_t>::max();
        if (!solver->drat->enabled()) {
            timeout = solver->propStats.otfHyperTime
            + solver->propStats.bogoProps
            + single_prop_tout;
        }

        //DFS is expensive, actually. So do BFS 50% of the time
        if (solver->conf.doStamp &&
            (force_stamp >= 1 || (solver->mtrand.randInt(1) == 0 && force_stamp == -1))
        ) {
            StampType stampType;
            if (force_stamp == 2) {
                stampType = StampType::STAMP_IRRED;
            } else if (force_stamp == 1) {
                stampType = StampType::STAMP_RED;
            } else {
                stampType = solver->mtrand.randInt(1) ? StampType::STAMP_IRRED : StampType::STAMP_RED;
            }
            failed = solver->propagate_dfs(stampType, timeout);
        } else {
            failed = solver->propagate_bfs(timeout);
        }

        if (check_timeout_due_to_hyperbin()) {
            return false;
        }
    } else {
        //No hyper-bin so we use regular propagate and regular analyze

        PropBy confl = solver->propagate<true>();
        if (!confl.isNULL()) {
            uint32_t  glue;
            uint32_t  backtrack_level;
            solver->analyze_conflict<true>(
                confl
                , backtrack_level  //return backtrack level here
                , glue             //return glue here
            );
            if (solver->learnt_clause.empty()) {
                solver->ok = false;
                return false;
            }
            assert(solver->learnt_clause.size() == 1);
            failed = ~(solver->learnt_clause[0]);
        }
    }

    return true;
}
Example #2
0
//Analyze why did we fail at decision level 1
Lit HyperEngine::analyzeFail(const PropBy propBy)
{
    //Clear out the datastructs we will be usin
    currAncestors.clear();

    //First, we set the ancestors, based on the clause
    //Each literal in the clause is an ancestor. So just 'push' them inside the
    //'currAncestors' variable
    switch(propBy.getType()) {
        case tertiary_t : {
            const Lit lit = ~propBy.lit3();
            if (varData[lit.var()].level != 0)
                currAncestors.push_back(lit);
            //intentionally falling through here
            //i.e. there is no 'break' here for a reason
        }
        case binary_t: {
            const Lit lit = ~propBy.lit2();
            if (varData[lit.var()].level != 0)
                currAncestors.push_back(lit);

            if (varData[failBinLit.var()].level != 0)
                currAncestors.push_back(~failBinLit);

            break;
        }

        case clause_t: {
            const uint32_t offset = propBy.get_offset();
            const Clause& cl = *cl_alloc.ptr(offset);
            for(size_t i = 0; i < cl.size(); i++) {
                if (varData[cl[i].var()].level != 0)
                    currAncestors.push_back(~cl[i]);
            }
            break;
        }

        case xor_t: {
            //in the future, we'll have XOR clauses. Not yet.
            assert(false);
            exit(-1);
            break;
        }

        case null_clause_t:
            assert(false);
            break;
    }

    Lit foundLit = deepest_common_ancestor();

    return foundLit;
}
Example #3
0
ClOffset DistillerLong::try_distill_clause_and_return_new(
    ClOffset offset
    , const bool red
    , const ClauseStats& stats
) {
    #ifdef DRAT_DEBUG
    if (solver->conf.verbosity >= 6) {
        cout << "Trying to distill clause:" << lits << endl;
    }
    #endif

    //Try to enqueue the literals in 'queueByBy' amounts and see if we fail
    solver->detachClause(offset, false);
    Clause& cl = *solver->cl_alloc.ptr(offset);
    (*solver->drat) << deldelay << cl << fin;

    uint32_t orig_size = cl.size();
    uint32_t i = 0;
    uint32_t j = 0;
    for (uint32_t sz = cl.size(); i < sz; i++) {
        if (solver->value(cl[i]) != l_False) {
            cl[j++] = cl[i];
        }
    }
    cl.resize(j);

    solver->new_decision_level();
    bool True_confl = false;
    PropBy confl;
    i = 0;
    j = 0;
    for (uint32_t sz = cl.size(); i < sz; i++) {
        const Lit lit = cl[i];
        lbool val = solver->value(lit);
        if (val == l_Undef) {
            solver->enqueue(~lit);
            cl[j++] = cl[i];

            maxNumProps -= 5;
            confl = solver->propagate<true>();
            if (!confl.isNULL()) {
                break;
            }
        } else if (val == l_False) {
            // skip
        } else {
            assert(val == l_True);
            cl[j++] = cl[i];
            True_confl = true;
            confl = solver->varData[cl[i].var()].reason;
            break;
        }
    }
    assert(solver->ok);
    cl.resize(j);

    //Couldn't simplify the clause
    if (j == orig_size && !True_confl && confl.isNULL()) {
        solver->cancelUntil<false, true>(0);
        solver->attachClause(cl);
        solver->drat->forget_delay();
        return offset;
    }

    #ifdef VERBOSE_DEBUG
    if (j < i && solver->conf.verbosity >= 5) {
        cout
        << "c Distillation branch effective." << endl
        << "c --> shortened cl:" << cl<< endl
        << "c --> orig size:" << orig_size << endl
        << "c --> new size:" << j << endl;
    }
    #endif

    bool lits_set = false;
    if (red && j > 1 && (!confl.isNULL() || True_confl)) {
        #ifdef VERBOSE_DEBUG
        if (solver->conf.verbosity >= 5) {
            cout
            << "c Distillation even more effective." << endl
            << "c --> orig shortened cl:" << cl << endl;
        }
        #endif
        maxNumProps -= 20;
        lits.clear();
        if (True_confl) {
            lits.push_back(cl[cl.size()-1]);
        }
        solver->simple_create_learnt_clause(confl, lits, True_confl);
        if (lits.size() < cl.size()) {
            #ifdef VERBOSE_DEBUG
            if (solver->conf.verbosity >= 5) {
                cout
                << "c --> more shortened cl:" << lits << endl;
            }
            #endif
            lits_set = true;
        }
    }
    solver->cancelUntil<false, true>(0);
    runStats.numLitsRem += orig_size - cl.size();
    runStats.numClShorten++;

    //Make new clause
    if (!lits_set) {
        lits.resize(cl.size());
        std::copy(cl.begin(), cl.end(), lits.begin());
    }
    solver->cl_alloc.clauseFree(offset);
    Clause *cl2 = solver->add_clause_int(lits, red, stats);
    (*solver->drat) << findelay;

    if (cl2 != NULL) {
        cl2->set_distilled(true);
        return solver->cl_alloc.get_offset(cl2);
    } else {
        //it became a bin/unit/zero
        return CL_OFFSET_MAX;
    }
}
Example #4
0
PropBy PropEngine::propagateBinFirst(
    #ifdef STATS_NEEDED
    AvgCalc<size_t>* watchListSizeTraversed
    #endif
) {
    PropBy confl;

    #ifdef VERBOSE_DEBUG_PROP
    cout << "Propagation started" << endl;
    #endif

    uint32_t qheadlong = qhead;

    startAgain:
    //Propagate binary clauses first
    while (qhead < trail.size() && confl.isNULL()) {
        const Lit p = trail[qhead++];     // 'p' is enqueued fact to propagate.
        watch_subarray_const ws = watches[(~p).toInt()];
        #ifdef STATS_NEEDED
        if (watchListSizeTraversed)
            watchListSizeTraversed->push(ws.size());
        #endif

        watch_subarray::const_iterator i = ws.begin();
        watch_subarray_const::const_iterator end = ws.end();
        propStats.bogoProps += ws.size()/10 + 1;
        for (; i != end; i++) {

            //Propagate binary clause
            if (i->isBinary()) {
                if (!propBinaryClause(i, p, confl)) {
                    break;
                }

                continue;
            }

            //Pre-fetch long clause
            if (i->isClause()) {
                if (value(i->getBlockedLit()) != l_True) {
                    const ClOffset offset = i->get_offset();
                    __builtin_prefetch(cl_alloc.ptr(offset));
                }

                continue;
            } //end CLAUSE
        }
    }

    PropResult ret = PROP_NOTHING;
    while (qheadlong < qhead && confl.isNULL()) {
        const Lit p = trail[qheadlong];     // 'p' is enqueued fact to propagate.
        watch_subarray ws = watches[(~p).toInt()];
        watch_subarray::iterator i = ws.begin();
        watch_subarray::iterator j = ws.begin();
        watch_subarray_const::const_iterator end = ws.end();
        propStats.bogoProps += ws.size()/4 + 1;
        for (; i != end; i++) {
            //Skip binary clauses
            if (i->isBinary()) {
                *j++ = *i;
                continue;
            }

            if (i->isTri()) {
                *j++ = *i;
                //Propagate tri clause
                ret = propTriClause(i, p, confl);
                 if (ret == PROP_SOMETHING || ret == PROP_FAIL) {
                    //Conflict or propagated something
                    i++;
                    break;
                } else {
                    //Didn't propagate anything, continue
                    assert(ret == PROP_NOTHING);
                    continue;
                }
            } //end TRICLAUSE

            if (i->isClause()) {
                ret = propNormalClause(i, j, p, confl);
                 if (ret == PROP_SOMETHING || ret == PROP_FAIL) {
                    //Conflict or propagated something
                    i++;
                    break;
                } else {
                    //Didn't propagate anything, continue
                    assert(ret == PROP_NOTHING);
                    continue;
                }
            } //end CLAUSE
        }
        while (i != end) {
            *j++ = *i++;
        }
        ws.shrink_(end-j);

        //If propagated something, goto start
        if (ret == PROP_SOMETHING) {
            goto startAgain;
        }

        qheadlong++;
    }

    #ifdef VERBOSE_DEBUG
    cout << "Propagation (propagateBinFirst) ended." << endl;
    #endif

    return confl;
}
Example #5
0
PropBy PropEngine::propagateAnyOrder()
{
    PropBy confl;

    #ifdef VERBOSE_DEBUG_PROP
    cout << "Fast Propagation started" << endl;
    #endif

    while (qhead < trail.size() && confl.isNULL()) {
        const Lit p = trail[qhead];     // 'p' is enqueued fact to propagate.
        watch_subarray ws = watches[(~p).toInt()];

        /*
        //propagate bin & tri
        for (watch_subarray::iterator i = ws.begin(), end = ws.end(); i != end; i++) {
            if (i->isBinary()) {
                if (!propBinaryClause(i, p, confl)) {
                    return confl;
                }
                continue;
            }

            //Propagate tri clause
            if (i->isTri()) {
                if (!propTriClauseAnyOrder(i, p, confl)) {
                    return confl;
                }
                continue;
            }
        }*/

        watch_subarray::iterator i = ws.begin();
        watch_subarray::iterator j = ws.begin();
        watch_subarray_const::const_iterator end = ws.end();
        if (update_bogoprops) {
            propStats.bogoProps += ws.size()/4 + 1;
        }

        for (; i != end; i++) {
            if (i->isBinary()) {
                *j++ = *i;
                if (!propBinaryClause<update_bogoprops>(i, p, confl)) {
                    i++;
                    break;
                }
                continue;
            }

            //Propagate tri clause
            if (i->isTri()) {
                *j++ = *i;
                if (!propTriClauseAnyOrder<update_bogoprops>(i, p, confl)) {
                    i++;
                    break;
                }
                continue;
            }

            //propagate normal clause
            if (i->isClause()) {
                if (!propNormalClauseAnyOrder<update_bogoprops>(i, j, p, confl)) {
                    i++;
                    break;
                }
                continue;
            }/* else {
                *j++ = *i;
            }*/

            assert(false);
        }
        while (i != end) {
            *j++ = *i++;
        }
        ws.shrink_(end-j);

        qhead++;
    }

    #ifdef VERBOSE_DEBUG
    cout << "Propagation (propagateAnyOrder) ended." << endl;
    #endif

    return confl;
}
Example #6
0
bool Prober::try_this(const Lit lit, const bool first, const uint64_t orig_num_props_to_do)
{
    //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->varData[lit.var()].depth = 0;
    if (solver->conf.verbosity >= 6) {
        cout
        << "c Probing lit " << lit
        << endl;
    }

    Lit failed = lit_Undef;
    if (solver->conf.otfHyperbin) {
        //Set timeout for ONE enqueue. This used so that in case ONE enqueue
        //takes too long (usually because of hyper-bin), we exit early
        uint64_t timeout = std::numeric_limits<uint64_t>::max();
        if (!solver->drup->enabled()) {
            timeout = solver->propStats.otfHyperTime
            + solver->propStats.bogoProps
            + (double)orig_num_props_to_do*solver->conf.single_probe_time_limit_perc;
        }

        //DFS is expensive, actually. So do BFS 50% of the time
        if (solver->conf.doStamp && solver->mtrand.randInt(1) == 0) {
            const StampType stampType = solver->mtrand.randInt(1) ? StampType::STAMP_IRRED : StampType::STAMP_RED;
            failed = solver->propagate_dfs(
                stampType
                , timeout //early-abort timeout
            );
        } else {
            failed = solver->propagate_bfs(
                timeout //early-abort timeout
            );
        }

        if (check_timeout_due_to_hyperbin()) {
            return solver->okay();
        }
    } else {
        //No hyper-bin so we use regular propagate and regular analyze

        PropBy confl = solver->propagate<true>();
        if (!confl.isNULL()) {
            uint32_t  glue;
            uint32_t  backtrack_level;
            solver->analyze_conflict(
                confl
                , backtrack_level  //return backtrack level here
                , glue             //return glue here
            );
            if (solver->learnt_clause.empty()) {
                solver->ok = false;
                return false;
            }
            assert(solver->learnt_clause.size() == 1);
            failed = ~(solver->learnt_clause[0]);
        }
    }

    if (failed != lit_Undef) {
        handle_failed_lit(lit, failed);
        return solver->ok;
    } else {
        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 Var var = thisLit.var();

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

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

    solver->cancelUntil<false>(0);
    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;

    //Add toEnqueue
    assert(solver->ok);
    runStats.bothSameAdded += toEnqueue.size();
    extraTime += 3*toEnqueue.size();
    return solver->fully_enqueue_these(toEnqueue);
}