/* 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; }