Example #1
0
/* Propage l'assignation d'une variable dans toutes les clauses dans lesquelles elle apparaît
   et arrête de surveiller une clause si setLitTrue/False renvoie true */
Variable* Variable::assignedFromDeducted(void)
{
    Variable* error = NULL;
    const Literal lit = Literal(this, _varState);
    
    DEBUG(6) << "Propagation du litéral : " << *this << std::endl;

    std::vector<Clause*>& cTrue  = _varState ? _litTrue : _litFalse;
    std::vector<Clause*>& cFalse = _varState ? _litFalse : _litTrue;
    std::vector<Clause*>::iterator it;

    /* On propage les litéraux qui deviennent satisfaits */
    it = cTrue.begin();
    while (it != cTrue.end())
    {
        if((*it)->setLitTrue(lit))
        {
            *it = cTrue.back();
            cTrue.pop_back();
        }
        else
            ++it;
    }

    /* On sépare en deux pour faire quelques tests de moins s'il y a une erreur */
    it = cFalse.begin();
    while (it != cFalse.end())
    {
        Clause* target = *it;
        if(target->setLitFalse(lit))
        {
            *it = cFalse.back();
            cFalse.pop_back();
        }
        else
            ++it;

        if(!target->isSatisfied())
        {
            const unsigned int fs = target->freeSize();
            /* Si une clause est contradictoire : on renvoie une erreur */
            if (fs == 0)
            {
                DEBUG(5) << "Contradiction (clause " << target << ", variable " << varNumber << ")" << std::endl;
                /* L'ereur vient de la variable qu'on est en train d'assigner */
                error = this;
                if (!_varState)
                    _deductedTrueFromClause = target;
                else
                    _deductedFalseFromClause = target;
                break;
            }

            /* Sinon, s'il n'y a pas déduction, ne rien faire. S'il y a une déduction on teste si elle est contradictoire */
            else if(fs == 1)
            {
                const Literal deduct = target->getRemaining();

                /* Si la déduction concerne une nouvelle variable, on l'ajoute */
                if(deduct.var()->isOlderIter(_endDeducted))
                {
                    deduct.var()->deductedFromFree(deduct.pos(), target);
                    DEBUG(5) << "Nouvelle déduction trouvée (clause " << target << ") :  " << deduct << std::endl;
                }
                /* Sinon, si on a déjà fait une déduction contraire, on a une contraduction. */
                else if(deduct.pos() != deduct.var()->_varState)
                {
                    DEBUG(5) << "Déduction contradictoire trouvée (clause " << target << ") :  " << deduct << std::endl;
                    error = deduct.var();
                    if(deduct.pos())
                        deduct.var()->_deductedTrueFromClause = target;
                    else
                        deduct.var()->_deductedFalseFromClause = target;
                    break;
                }
                /* Sinon, si on a déjà fait la même déduction, on ne fait rien. */
                else
                {
                    DEBUG(6) << "Déduction (re-)trouvée (clause " << target << ") :  " << deduct << std::endl;
                }
            }
        }
    }

    /*  On finit la propagation (n'arrive que s'il y a eu une erreur) */
    while (it != cFalse.end())
    {
        if((*it)->setLitFalse(lit))
        {
            *it = cFalse.back();
            cFalse.pop_back();
        }
        else
            ++it;
    }
    return error;
}