Пример #1
0
bool LinearPropagator::propagate_true(const LinearConstraint& l)
{
    assert(l.getRelation()==LinearConstraint::Relation::LE);
    auto minmax = computeMinMax(l);
    if (minmax.second <= l.getRhs())
        return true;

    for (auto i : l.getViews())
    {
        auto r = vs_.getCurrentRestrictor(i);
        auto wholeRange = vs_.getRestrictor(i); 
        std::pair<int64,int64> mm;
        mm.first = minmax.first - r.lower();
        mm.second = minmax.second - r.upper();

            int64 up = l.getRhs() - mm.first;
            if (up < r.lower())
            {
                //std::cout << "Constrain Variable " << i.first << " with new upper bound " << up << std::endl;
                return false;
            }
            if (up < r.upper())
            {
                //std::cout << "Constrain Variable " << i.first << " with new upper bound " << up << std::endl;
                //auto newUpper = std::lower_bound(wholeRange.begin(), wholeRange.end(), up);
                auto newUpper = std::upper_bound(wholeRange.begin(), wholeRange.end(), up);
                if (!constrainUpperBound(newUpper)) // +1 is needed, as it is in iterator pointing after the element
                    return false;
                minmax.first = mm.first + r.lower();
                minmax.second = mm.second + *(newUpper-1);
            }
    }
    return true;
}
Пример #2
0
std::vector<LinearLiteralPropagator::LinearConstraintClause> LinearLiteralPropagator::propagate_true(const ReifiedLinearConstraint& rl)
{
    const LinearConstraint& l = rl.l;
    assert(l.getRelation()==LinearConstraint::Relation::LE);
    std::vector<LinearConstraintClause> ret;
    LinearConstraintClause::itervec clause;
    auto minmax = computeMinMax(l, clause);
    if (minmax.second <= l.getRhs())
        return ret;

    //std::cout << "trying to propagate " << l << std::endl;
    auto views = l.getViews();
    for (std::size_t index=0; index < views.size(); ++index)
    {
        auto& i = views[index];
        auto wholeRange = vs_.getVariableStorage().getRestrictor(i);
        assert(wholeRange.size()>0);
        auto r = vs_.getVariableStorage().getCurrentRestrictor(i);
        std::pair<int64,int64> mm;
        mm.first = minmax.first - r.lower();
        mm.second = minmax.second - r.upper();
        
        //Literal prop = s_.falseLit();
        bool prop = false;
        Restrictor::ViewIterator propIt(wholeRange.begin());
        bool conflict = false;

        int64 up = l.getRhs() - mm.first;
        
        
        //// check if this returns the correct literals,
        /// see translatorClauseChecker::add, there is a positive and a negative add
        if (up < wholeRange.lower()) // derive false
        {
            //std::cout << "Constrain View " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl;
            propIt=wholeRange.begin();//can be removed
            conflict = true;
        }
        else
            if (up < r.upper())
            {
                //std::cout << "Constrain Variable " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl;
                auto newUpper = std::upper_bound(wholeRange.begin(), wholeRange.end(), up, [](int64 val, int64 it){ return it > val; });
                //assert(newUpper != r.end()); /// should never be able to happen, as up < r.upper().first, so there is something which is smaller, this means we do not need r ?
                if (newUpper==wholeRange.begin())
                {
                    propIt = newUpper;
                    conflict=true;
                }
                else
                {
                    propIt = newUpper;
                    --newUpper;
                    prop = true;
                    //prop = vs_.getVariableCreator().getLiteral(newUpper);
                    conflict = !constrainUpperBound((newUpper+1)); // +1 is needed, as it is an iterator pointing after the element
                    minmax.first = mm.first + r.lower();
                    minmax.second =  mm.second + *newUpper;
                    //minmax = mm + std::minmax(i.second*(int64)r.lower(),i.second*(int64)((*newUpper)));
                }
            }

        if (prop || conflict)
        {
            LinearConstraintClause c(rl);
            LinearConstraintClause::itervec aux(clause);
            aux[index] = propIt;
            c.setClause(std::move(aux),index);
            c.setConflict(conflict);
            ret.emplace_back(c);
        }
        if (conflict)
            break;
    }
    //When i changed a bound, the reason for the next ones can change, right ? No! only the upper/lower bound is changes, the other bound is used for reason
    return ret;
}
Пример #3
0
/// return false if the domain is empty
void ConstraintStorage::constrainLowerBound(const View &u, const Solver& s)
{
    constrainUpperBound(u*-1,s);
}
Пример #4
0
void LinearLiteralPropagator::propagate_true(const ReifiedLinearConstraint& rl)
{
    const LinearConstraint& l = rl.l;
    assert(l.getRelation()==LinearConstraint::Relation::LE);

    propClause_.clear();
    auto minmax = computeMinMax(l, propClause_);
    if (minmax.second <= l.getRhs())
        return;

    if (conf_.propStrength<=2)
    {
        if (minmax.first > l.getRhs())
        {
            propClauses_.emplace_back(std::make_pair(~rl.v,std::move(propClause_)));
        }
        return;
    }

    //std::cout << "trying to propagate " << l << std::endl;
    auto& views = l.getViews();
    for (std::size_t index=0; index < views.size(); ++index)
    {
        auto& i = views[index];
        auto wholeRange = vs_.getVariableStorage().getRestrictor(i);
        assert(wholeRange.size()>0);
        auto r = vs_.getVariableStorage().getCurrentRestrictor(i);
        assert(r.begin() < r.end());
        std::pair<int64,int64> mm;
        mm.first = minmax.first - r.lower();
        mm.second = minmax.second - r.upper();

        //Literal prop = s_.falseLit();
        bool prop = false;
        Restrictor::ViewIterator propIt(wholeRange.begin());
        bool conflict = false;

        int64 up = l.getRhs() - mm.first;

        if (up < wholeRange.lower()) // derive false
        {
            //std::cout << "Constrain View " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl;
            //propIt=wholeRange.begin();//can be removed
            conflict = true;
        }
        else
            if (up < r.upper())
            {
                //std::cout << "Constrain Variable " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl;
                //std::cout << "This Variable before had domain " << r.lower() << " .. " << r.upper() << std::endl;
                auto newUpper = order::wrap_upper_bound(wholeRange.begin(), r.end(), up);
                //assert(newUpper != r.end()); /// should never be able to happen, as up < r.upper().first, so there is something which is smaller, this means we do not need r ?
                propIt = newUpper;
                if (newUpper==wholeRange.begin())
                {
                    conflict=true;
                }
                else
                {
                    --newUpper;
                    prop = true;
                    //prop = vs_.getVariableCreator().getLiteral(newUpper);
                    //std::cout << "the upper bound not included for this view will be " << *(newUpper+1) << std::endl;
                    conflict = !constrainUpperBound((newUpper+1)); // +1 is needed, as it is an iterator pointing after the element
                    //minmax.first = mm.first + r.lower();
                    minmax.second =  mm.second + *newUpper;
                    //minmax = mm + std::minmax(i.second*(int64)r.lower(),i.second*(int64)((*newUpper)));
                }
            }

        if (prop || conflict)
        {
            itervec aux;
            if (conflict) aux = std::move(propClause_);
            else aux = propClause_;
            aux[index] = propIt;
            propClauses_.emplace_back(std::make_pair(~rl.v,std::move(aux)));
        }
        if (conflict)
            break;
    }
    //When i changed a bound, the reason for the next ones can change, right ? No! only the upper/lower bound is changes, the other bound is used for reason
}