bool BitvectorTheory::handleITE(const FormulaT& ifterm, const types::TermType& thenterm, const types::TermType& elseterm, types::TermType& result, TheoryError& errors) { types::BVTerm thent; types::BVTerm elset; if (!termConverter(thenterm, thent)) { errors.next() << "Failed to construct ITE, the then-term \"" << thenterm << "\" is unsupported."; return false; } if (!termConverter(elseterm, elset)) { errors.next() << "Failed to construct ITE, the else-term \"" << elseterm << "\" is unsupported."; return false; } if (thent.width() != elset.width()) { errors.next() << "Failed to construct ITE, the then-term \"" << thent << "\" and the else-term \"" << elset << "\" have different widths."; return false; } if (ifterm.isTrue()) { result = thent; return true; } if (ifterm.isFalse()) { result = elset; return true; } carl::SortManager& sm = carl::SortManager::getInstance(); carl::Variable var = carl::freshVariable(carl::VariableType::VT_BITVECTOR); state->artificialVariables.emplace_back(var); carl::BVVariable bvvar(var, sm.index(this->bvSort, {thent.width()})); state->auxiliary_variables.insert(bvvar); types::BVTerm vart = types::BVTerm(carl::BVTermType::VARIABLE, bvvar); FormulaT consThen = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, vart, thent)); FormulaT consElse = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, vart, elset)); state->global_formulas.emplace_back(FormulaT(carl::FormulaType::IMPLIES, {ifterm, consThen})); state->global_formulas.emplace_back(FormulaT(carl::FormulaType::IMPLIES, {FormulaT(carl::FormulaType::NOT,ifterm), consElse})); result = vart; return true; }
FormulaT MCBModule<Settings>::applyReplacements(const FormulaT& f) { if (mChoices.empty()) return f; std::set<AVar> variables; std::map<FormulaT, FormulaT> repl; for (const auto& r: mChoices) { variables.insert(r.first); for (const auto& f: r.second) { BVar v = f.second.first; const FormulaT& form = f.second.second; repl.emplace(form, FormulaT(v)); } } carl::FormulaSubstitutor<FormulaT> subs; SMTRAT_LOG_DEBUG("smtrat.mcb", "Applying " << repl << " on \n\t" << f); FormulaT res = subs.substitute(f, repl); SMTRAT_LOG_DEBUG("smtrat.mcb", "Resulting in\n\t" << res); mRemaining.clear(); res.allVars(mRemaining); FormulasT equiv; for (const auto& v: variables) { if (mRemaining.count(v) > 0) { // Variable is still in the formula for (const auto& r: mChoices.at(v)) { equiv.push_back(FormulaT(carl::FormulaType::IFF, {FormulaT(r.second.first), r.second.second})); } } else { // Variable has been eliminated ModelVariable var(v); std::map<BVar,Rational> assignment; for (const auto& c: mChoices.at(v)) { assignment.emplace(c.second.first, c.first); } SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding " << var << " = " << assignment); mAssignments.emplace(var, carl::createSubstitution<Rational,Poly,MCBModelSubstitution>(assignment)); } for (const auto& c1: mChoices.at(v)) { for (const auto& c2: mChoices.at(v)) { if (c1.second.first >= c2.second.first) continue; equiv.push_back(FormulaT(carl::FormulaType::OR, {FormulaT(c1.second.first).negated(), FormulaT(c2.second.first).negated()})); SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding exclusion " << equiv.back()); } } } if (equiv.empty()) return res; SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding equivalences " << equiv); equiv.push_back(res); return FormulaT(carl::FormulaType::AND, std::move(equiv)); }
void MCBModule<Settings>::collectChoices(const FormulaT& formula) { if (formula.getType() != carl::FormulaType::OR) return; FormulaT::ConstraintBounds cb; collectBounds(cb, formula, false); if (cb.empty()) return; for (const auto& poly: cb) { if (!poly.first.isVariable()) continue; AVar var = poly.first.getSingleVariable(); std::vector<std::pair<Rational,FormulaT>> choices; for (const auto& entry: poly.second) { if (entry.second.first != carl::Relation::EQ) break; choices.emplace_back(entry.first, entry.second.second); } if (choices.size() != poly.second.size()) continue; auto& m = mChoices[var]; for (const auto& c: choices) { auto it = m.find(c.first); if (it == m.end()) { m.emplace(c.first, std::make_pair(carl::freshBooleanVariable(), c.second)); } } } }
void MCBModule<Settings>::collectBounds(FormulaT::ConstraintBounds& cb, const FormulaT& formula, bool conjunction) const { for (const auto& f: formula.subformulas()) { if (f.getType() == carl::FormulaType::CONSTRAINT || (f.getType() == carl::FormulaType::NOT && f.subformula().getType() == carl::FormulaType::CONSTRAINT)) { FormulaT::addConstraintBound(cb, f, conjunction); } } }
FormulaT EMModule<Settings>::eliminateEquation(const FormulaT& formula) { if (formula.getType() != carl::FormulaType::CONSTRAINT) return formula; carl::Relation rel = formula.constraint().relation(); switch (rel) { case carl::Relation::EQ: case carl::Relation::NEQ: { auto factors = formula.constraint().factorization(); FormulasT res; for (const auto& factor: factors) { res.emplace_back(factor.first, rel); } carl::FormulaType ft = (rel == carl::Relation::EQ) ? carl::FormulaType::OR : carl::FormulaType::AND; FormulaT result(ft, std::move(res)); if (result != formula) { SMTRAT_LOG_INFO("smtrat.em", "Translated\n\t" << formula << "\nto\n\t" << result); } return result; } default: return formula; } }
Answer EMModule<Settings>::checkCore() { auto receivedFormula = firstUncheckedReceivedSubformula(); while (receivedFormula != rReceivedFormula().end()) { FormulaT formula = receivedFormula->formula(); if (receivedFormula->formula().propertyHolds(carl::PROP_CONTAINS_NONLINEAR_POLYNOMIAL)) { formula = mVisitor.visitResult(receivedFormula->formula(), eliminateEquationFunction); } if (formula.isFalse()) { receivedFormulasAsInfeasibleSubset(receivedFormula); return UNSAT; } if (!formula.isTrue()) { addSubformulaToPassedFormula(formula, receivedFormula->formula()); } ++receivedFormula; } Answer ans = runBackends(); if (ans == UNSAT) getInfeasibleSubsets(); return ans; }
Answer CNFerModule::checkCore() { auto receivedSubformula = firstUncheckedReceivedSubformula(); while( receivedSubformula != rReceivedFormula().end() ) { /* * Add the currently considered formula of the received constraint as clauses * to the passed formula. */ FormulaT formulaToAssertInCnf = receivedSubformula->formula().toCNF( true, true, true ); if( formulaToAssertInCnf.getType() == TRUE ) { // No need to add it. } else if( formulaToAssertInCnf.getType() == FALSE ) { receivedFormulasAsInfeasibleSubset( receivedSubformula ); return UNSAT; } else { if( formulaToAssertInCnf.getType() == AND ) { for( const FormulaT& subFormula : formulaToAssertInCnf.subformulas() ) { #ifdef SMTRAT_DEVOPTION_Statistics mpStatistics->addClauseOfSize( subFormula.size() ); #endif addSubformulaToPassedFormula( subFormula, receivedSubformula->formula() ); } } else { #ifdef SMTRAT_DEVOPTION_Statistics mpStatistics->addClauseOfSize( receivedSubformula->formula().size() ); #endif addSubformulaToPassedFormula( formulaToAssertInCnf, receivedSubformula->formula() ); } } ++receivedSubformula; } //No given formulas is SAT but only if no other run was before if( rPassedFormula().empty() && solverState() == UNKNOWN ) { return SAT; } else { #ifdef SMTRAT_DEVOPTION_Statistics carl::Variables avars; rPassedFormula().arithmeticVars( avars ); mpStatistics->nrOfArithVariables() = avars.size(); carl::Variables bvars; rPassedFormula().booleanVars( bvars ); mpStatistics->nrOfBoolVariables() = bvars.size(); #endif Answer a = runBackends(); if( a == UNSAT ) { getInfeasibleSubsets(); } return a; } }