Beispiel #1
0
	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;
	}
Beispiel #2
0
	FormulaT MixedSignEncoder::findSubEncoding(const ConstraintT& constraint) {
		FormulaT chosenEncoding;
		bool hasEncoded = false;
		
		if (mShortFormulaEncoder.canEncode(constraint)) {
			boost::optional<FormulaT> shortEncoding = mShortFormulaEncoder.encode(constraint);
			if (shortEncoding) {
				chosenEncoding = *shortEncoding;
				hasEncoded = true;
			}
		} else if (mCardinalityEncoder.canEncode(constraint)) {
			boost::optional<FormulaT> cardinalityEncoding = mCardinalityEncoder.encode(constraint);
			if (cardinalityEncoding) {
				chosenEncoding = *cardinalityEncoding;
				hasEncoded = true;
			}
		} else if (mLongFormulaEncoder.canEncode(constraint)) {
			boost::optional<FormulaT> longEncoding = mLongFormulaEncoder.encode(constraint);
			if (longEncoding) {
				chosenEncoding = *longEncoding;
				hasEncoded = true;
			}
		}

		if (!hasEncoded) {
			chosenEncoding = FormulaT(constraint);
		}

		return chosenEncoding;
	}
Beispiel #3
0
		bool apply(const std::vector<FormulaT>& arguments, types::TermType& result, TheoryError& errors) const {
			if (arguments.size() != 2) {
				errors.next() << "Operator \"implies\" may only have a single argument.";
				return false;
			}
			result = FormulaT(carl::FormulaType::IMPLIES, {arguments[0], arguments[1]});
			return true;
		}
Beispiel #4
0
		bool apply(const std::vector<types::BVTerm>& arguments, types::TermType& result, TheoryError& errors) const {
			if (arguments.size() != 2) {
				errors.next() << "The operator \"" << type << "\" expects exactly two arguments.";
				return false;
			}
			result = FormulaT(types::BVConstraint::create(type, arguments[0], arguments[1]));
			return true;
		}
Beispiel #5
0
	bool CoreTheory::handleDistinct(const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
		std::vector<FormulaT> args;
		if (!convertArguments(arguments, args, errors)) return false;
		result = expandDistinct(args, [](const FormulaT& a, const FormulaT& b){
			return FormulaT(carl::FormulaType::XOR, {a, b});
		});
		return true;
	}
Beispiel #6
0
	bool BitvectorTheory::handleDistinct(const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
		std::vector<carl::BVTerm> args;
		if (!vectorConverter(arguments, args, errors)) return false;
		result = expandDistinct(args, [](const carl::BVTerm& a, const carl::BVTerm& b){
			return FormulaT(carl::BVConstraint::create(carl::BVCompareRelation::NEQ, a, b));
		});
		return true;
	}
Beispiel #7
0
	bool CoreTheory::functionCall(const Identifier& identifier, const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
		std::vector<FormulaT> args;
		if (!convertArguments(arguments, args, errors)) return false;
		
		if (boost::iequals(identifier.symbol, "=")) {
			result = FormulaT(carl::FormulaType::IFF, FormulasT(args.begin(), args.end()));
			return true;
		}
		return false;
	}
Beispiel #8
0
	bool BitvectorTheory::functionCall(const Identifier& identifier, const std::vector<types::TermType>& arguments, types::TermType& result, TheoryError& errors) {
		if (identifier.symbol == "=") {
			if (arguments.size() == 2) {
				std::vector<types::BVTerm> args;
				if (!vectorConverter(arguments, args, errors)) return false;
				result = FormulaT(types::BVConstraint::create(carl::BVCompareRelation::EQ, args[0], args[1]));
				return true;
			}
			errors.next() << "Operator \"" << identifier << "\" expects exactly two arguments, but got " << arguments.size() << ".";
			return false;
		}
		errors.next() << "Invalid operator \"" << identifier << "\".";
		return false;
	}
Beispiel #9
0
	bool CoreTheory::handleITE(const FormulaT& ifterm, const types::TermType& thenterm, const types::TermType& elseterm, types::TermType& result, TheoryError& errors) {
		FormulaT thenf;
		FormulaT elsef;
		if (!convertTerm(thenterm, thenf)) {
			errors.next() << "Failed to construct ITE, the then-term \"" << thenterm << "\" is unsupported.";
			return false;
		}
		if (!convertTerm(elseterm, elsef)) {
			errors.next() << "Failed to construct ITE, the else-term \"" << elseterm << "\" is unsupported.";
			return false;
		}
		result = FormulaT(carl::FormulaType::ITE, {ifterm, thenf, elsef});
		return true;
	}
Beispiel #10
0
	bool CoreTheory::convertTerm(const types::TermType& term, FormulaT& result) {
		if (boost::get<FormulaT>(&term) != nullptr) {
			result = boost::get<FormulaT>(term);
			return true;
		} else if (boost::get<carl::Variable>(&term) != nullptr) {
			if (boost::get<carl::Variable>(term).getType() == carl::VariableType::VT_BOOL) {
				result = FormulaT(boost::get<carl::Variable>(term));
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
Beispiel #11
0
	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));
	}
Beispiel #12
0
	Answer MCBModule<Settings>::checkCore()
	{
		mRemaining.clear();
		mChoices.clear();
		carl::FormulaVisitor<FormulaT> visitor;
		auto receivedFormula = firstUncheckedReceivedSubformula();
		while (receivedFormula != rReceivedFormula().end()) {
			visitor.visit(receivedFormula->formula(), collectChoicesFunction);
			receivedFormula++;
		}
		FormulaT newFormula = applyReplacements(FormulaT(rReceivedFormula()));
		clearPassedFormula();
		addSubformulaToPassedFormula(newFormula);
		
		Answer ans = runBackends();
		if (ans == UNSAT) {
			generateTrivialInfeasibleSubset();
		}
		return ans;
	}
Beispiel #13
0
	boost::optional<FormulaT> MixedSignEncoder::doEncode(const ConstraintT& constraint) {
		// first partition into positive and negative terms
		std::vector<TermT> positiveTerms;
		std::vector<TermT> negativeTerms;

		for (const auto& term : constraint.lhs()) {
			if (term.isConstant()) continue;
			
			if (term.coeff() > 0) {
				positiveTerms.push_back(term);
			} else {
				negativeTerms.push_back(term);
			}
		}

		Poly lhs;
		Poly rhs;
		for (const auto& term : positiveTerms) {
			lhs += term;
		}

		for (const auto& term : negativeTerms) {
			rhs -= term;
		} 

		if (constraint.relation() == carl::Relation::LEQ) { // we assume mixed signs
			// x1 + x2 - x3 - x4 - 1 <= 0 iff x1 + x2 -1 <= x3 + x4
			// lhsValues -1, 0, 1
			// rhs Value 0, 1, 2
			// x1 + x2 - 1 >= -1 impl. x3 + x4 >= - 1
			// x1 + x2 - 1 >= 0 impl x3 + x4 >= 0
			// x1 + x2 - 1 >= 1 impl x3 + x4 >= 1

			// now we can express the constraint as sum of positive terms <= negative sum of negative terms - constantPart
			// this holds iff
			// take all possible subsetsums of our new lhs. For each of these sums b_i we construct
			// encode(lhs + constant >= b_i) implies encode(rhs >= b_i)

			std::vector<Rational> subsetsums = calculateSubsetsums(positiveTerms);
			FormulasT conjunction;
			for (const auto& sum : subsetsums) {
				ConstraintT lhsImplication(lhs - sum, carl::Relation::GEQ); // poly lhs + constantPart >= bi
				ConstraintT rhsImplication(rhs - sum - constraint.constantPart(), carl::Relation::GEQ); // rhs >= bi


				FormulaT chosenLhsEncoding = findSubEncoding(mNormalizer.trim(lhsImplication));
				FormulaT chosenRhsEncoding = findSubEncoding(mNormalizer.trim(rhsImplication));

				conjunction.push_back(FormulaT(carl::FormulaType::IMPLIES, chosenLhsEncoding, chosenRhsEncoding));
			}

			return FormulaT(carl::FormulaType::AND, conjunction);
		}

		if (constraint.relation() == carl::Relation::EQ) {
			// x1 + x2 - x3 - x4 - 1= 0 iff x1 + x2 -1 = x3 + x4
			// positiveSums: -1, 0, 1
			// negativeSums: 0, 1, 2

			// x3 + x4 = 0 impl. x1 + x2 -1 = 0 
			// x3 + x4 = 1 impl. x1 + x2 -1 = 1
			// x3 + x4 = 2 impl. x1 + x2 -1 = 2
			// x1 + x2 -1 = -1 impl. x3 + x4 = -1
			// x1 + x2 -1 = 0 impl. x3 + x4 = 0
			// x1 + x2 -1 = 1 impl. x3 + x4 = 1

			std::vector<Rational> subsetsumsPositive = calculateSubsetsums(positiveTerms);
			std::vector<Rational> subsetsumsNegative = calculateSubsetsums(negativeTerms);
			FormulasT conjunction;
			for (const auto& sum : subsetsumsPositive) {
				ConstraintT lhsImplication(lhs - sum, carl::Relation::EQ);
				ConstraintT rhsImplication(rhs - sum - constraint.constantPart(), carl::Relation::EQ);

				FormulaT chosenLhsEncoding = findSubEncoding(mNormalizer.trim(lhsImplication));
				FormulaT chosenRhsEncoding = findSubEncoding(mNormalizer.trim(rhsImplication));

				conjunction.push_back(FormulaT(carl::FormulaType::IMPLIES, chosenLhsEncoding, chosenRhsEncoding));
			}

			for (const auto& sum : subsetsumsNegative) {
				ConstraintT lhsImplication(lhs - constraint.constantPart() - sum, carl::Relation::EQ);
				ConstraintT rhsImplication(rhs - sum, carl::Relation::EQ);

				FormulaT chosenLhsEncoding = findSubEncoding(mNormalizer.trim(lhsImplication));
				FormulaT chosenRhsEncoding = findSubEncoding(mNormalizer.trim(rhsImplication));

				conjunction.push_back(FormulaT(carl::FormulaType::IMPLIES, chosenRhsEncoding, chosenLhsEncoding));
			}

			return FormulaT(carl::FormulaType::AND, conjunction);	
		}

		return {};
	}
Beispiel #14
0
 Answer CubeLIAModule<Settings>::checkCore()
 {
     #ifdef DEBUG_CUBELIAMODULE
     print();
     #endif
     Answer ans;
     if( !rReceivedFormula().isRealConstraintConjunction() )
     {
         #ifdef DEBUG_CUBELIAMODULE
         std::cout << "Call internal LRAModule:" << std::endl;
         mLRA.print();
         #endif
         mLRA.clearLemmas();
         mLRAFormula->updateProperties();
         ans = mLRA.check( false, mFullCheck, mMinimizingCheck );
         switch( ans )
         {
             case SAT:
             {
                 clearModel();
                 // Get the model of mLRA
                 mLRA.updateModel();
                 const Model& relaxedModel = mLRA.model();
                 auto iter = mRealToIntVarMap.begin();
                 for( auto& ass : relaxedModel )
                 {
                     assert( iter != mRealToIntVarMap.end() );
                     // Round the result to the next integer
                     mModel.emplace_hint( mModel.end(), iter->second, carl::round( ass.second.asRational() ) );
                     ++iter;
                 }
                 // Check if the rounded model satisfies the received formula
                 bool receivedFormulaSatisfied = true;
                 for( const FormulaWithOrigins& fwo : rReceivedFormula() )
                 {
                     unsigned res = satisfies( mModel, fwo.formula() );
                     switch( res )
                     {
                         case 0:
                         case 2:
                             receivedFormulaSatisfied = false;
                         default:
                             break;
                     }
                     if( !receivedFormulaSatisfied )
                         break;
                 }
                 // If we found a model, we know that the formula is satisfiable, otherwise, we have to call the backends on the received formula
                 if( receivedFormulaSatisfied )
                 {
                     mModelUpdated = true;
                     return SAT;
                 }
                 clearModel();
                 break;
             }
             case UNSAT:
             {
                 if( Settings::exclude_unsatisfiable_cube_space )
                 {
                     // Exclude the space for which mLRA has detected unsatisfiability
                     for( auto& infsubset : mLRA.infeasibleSubsets() )
                     {
                         FormulasT formulas;
                         for( auto& formula : infsubset )
                             formulas.push_back( formula.negated() );
                         addLemma( FormulaT( carl::FormulaType::OR, formulas ) );
                     }
                 }
                 break;
             }
             default:
                 assert( false );
         }
     }
     #ifdef DEBUG_CUBELIAMODULE
     std::cout << "Call Backends:" << std::endl;
     #endif
     // Run backends on received formula
     ans = runBackends();
     if( ans == UNSAT )
         getInfeasibleSubsets();
     else if( ans == SAT )
         mModelUpdated = false;
     return ans;
 }
Beispiel #15
0
	void CoreTheory::addConstants(qi::symbols<char, types::ConstType>& constants) {
		constants.add("true", types::ConstType(FormulaT(carl::FormulaType::TRUE)));
		constants.add("false", types::ConstType(FormulaT(carl::FormulaType::FALSE)));
	}
Beispiel #16
0
		virtual FormulaT representingFormula( const ModelVariable& mv ) {
			assert(false);
			return FormulaT();
		}
Beispiel #17
0
		bool apply(const std::vector<FormulaT>& arguments, types::TermType& result, TheoryError& ) const {
			result = FormulaT(type, arguments);
			return true;
		}