Browse Source
			
			
			Initial MathSat integration.
			
				
		Initial MathSat integration.
	
		
	
			
				Expression adapter, solving, unsat assumptions implemented
cmake and tests missing
allsat and interpolation not yet implemented
Former-commit-id: 5177775fbe
			
			
				main
			
			
		
				 3 changed files with 775 additions and 0 deletions
			
			
		- 
					370src/adapters/MathSatExpressionAdapter.h
- 
					321src/solver/MathSatSmtSolver.cpp
- 
					84src/solver/MathSatSmtSolver.h
| @ -0,0 +1,370 @@ | |||
| /* | |||
| * MathSatExpressionAdapter.h | |||
| * | |||
| *      Author: David Korzeniewski | |||
| */ | |||
| 
 | |||
| #ifndef STORM_ADAPTERS_MATHSATEXPRESSIONADAPTER_H_ | |||
| #define STORM_ADAPTERS_MATHSATEXPRESSIONADAPTER_H_ | |||
| 
 | |||
| #include "storm-config.h" | |||
| 
 | |||
| #include <stack> | |||
| 
 | |||
| #include "mathsat.h" | |||
| 
 | |||
| #include "storage/expressions/Expressions.h" | |||
| #include "storage/expressions/ExpressionVisitor.h" | |||
| #include "src/exceptions/ExceptionMacros.h" | |||
| #include "src/exceptions/ExpressionEvaluationException.h" | |||
| #include "src/exceptions/InvalidTypeException.h" | |||
| #include "src/exceptions/NotImplementedException.h" | |||
| 
 | |||
| namespace storm { | |||
| 	namespace adapters { | |||
| 
 | |||
| 		class MathSatExpressionAdapter : public storm::expressions::ExpressionVisitor { | |||
| 		public: | |||
| 			/*! | |||
| 			* Creates a MathSatExpressionAdapter over the given MathSAT enviroment. | |||
| 			* | |||
| 			* @param context A reference to the MathSAT enviroment over which to build the expressions. Be careful to guarantee | |||
| 			* the lifetime of the context as long as the instance of this adapter is used. | |||
| 			* @param variableToDeclMap A mapping from variable names to their corresponding MathSAT Declarations. | |||
| 			*/ | |||
| 			MathSatExpressionAdapter(msat_env& env, std::map<std::string, msat_decl> const& variableToDeclMap) : env(env), stack(), variableToDeclMap(variableToDeclMap) { | |||
| 				// Intentionally left empty. | |||
| 			} | |||
| 
 | |||
| 			/*! | |||
| 			* Translates the given expression to an equivalent term for MathSAT. | |||
| 			* | |||
| 			* @param expression The expression to translate. | |||
| 			* @param createMathSatVariables If set to true a solver variable is created for each variable in expression that is not | |||
| 			*                          yet known to the adapter. (i.e. values from the variableToExpressionMap passed to the constructor | |||
| 			*                          are not overwritten) | |||
| 			* @return An equivalent term for MathSAT. | |||
| 			*/ | |||
| 			msat_term translateExpression(storm::expressions::Expression const& expression, bool createMathSatVariables = false) { | |||
| 				//LOG4CPLUS_TRACE(logger, "Translating expression:\n" << expression->toString()); | |||
| 				expression.accept(this); | |||
| 				msat_term result = stack.top(); | |||
| 				stack.pop(); | |||
| 				if (MSAT_ERROR_TERM(result)) { | |||
| 					//LOG4CPLUS_WARN(logger, "Translating term to MathSAT returned an error!"); | |||
| 				} | |||
| 
 | |||
| 				char* repr = msat_term_repr(result); | |||
| 				//LOG4CPLUS_TRACE(logger, "Result is:\n" << repr); | |||
| 				msat_free(repr); | |||
| 				return result; | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::BinaryBooleanFunctionExpression const* expression) override { | |||
| 				expression->getFirstOperand()->accept(this); | |||
| 				expression->getSecondOperand()->accept(this); | |||
| 
 | |||
| 				msat_term rightResult = stack.top(); | |||
| 				stack.pop(); | |||
| 				msat_term leftResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				//char* repr = msat_term_repr(leftResult); | |||
| 				//LOG4CPLUS_TRACE(logger, "LHS: "<<repr); | |||
| 				//msat_free(repr); | |||
| 				//repr = msat_term_repr(rightResult); | |||
| 				//LOG4CPLUS_TRACE(logger, "RHS: "<<repr); | |||
| 				//msat_free(repr); | |||
| 
 | |||
| 				switch (expression->getOperatorType()) { | |||
| 					case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::And: | |||
| 						stack.push(msat_make_and(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Or: | |||
| 						stack.push(msat_make_or(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Iff: | |||
| 						stack.push(msat_make_iff(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown boolean binary operator: '" << expression->getOperatorType() << "' in expression " << expression << "."; | |||
| 				} | |||
| 
 | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::BinaryNumericalFunctionExpression const* expression) override { | |||
| 				expression->getFirstOperand()->accept(this); | |||
| 				expression->getSecondOperand()->accept(this); | |||
| 
 | |||
| 				msat_term rightResult = stack.top(); | |||
| 				stack.pop(); | |||
| 				msat_term leftResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				switch (expression->getOperatorType()) { | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Plus: | |||
| 						stack.push(msat_make_plus(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Minus: | |||
| 						stack.push(msat_make_plus(env, leftResult, msat_make_times(env, msat_make_number(env, "-1"), rightResult))); | |||
| 						break; | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Times: | |||
| 						stack.push(msat_make_times(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Divide: | |||
| 						throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 							<< "Unsupported numerical binary operator: '/' (division) in expression " << expression << "."; | |||
| 						break; | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Min: | |||
| 						stack.push(msat_make_term_ite(env, msat_make_leq(env, leftResult, rightResult), leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryNumericalFunctionExpression::OperatorType::Max: | |||
| 						stack.push(msat_make_term_ite(env, msat_make_leq(env, leftResult, rightResult), rightResult, leftResult)); | |||
| 						break; | |||
| 					default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown numerical binary operator: '" << expression->getOperatorType() << "' in expression " << expression << "."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::BinaryRelationExpression const* expression) override { | |||
| 				expression->getFirstOperand()->accept(this); | |||
| 				expression->getSecondOperand()->accept(this); | |||
| 
 | |||
| 				msat_term rightResult = stack.top(); | |||
| 				stack.pop(); | |||
| 				msat_term leftResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				switch (expression->getRelationType()) { | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::Equal: | |||
| 						if (expression->getFirstOperand()->getReturnType() == storm::expressions::ExpressionReturnType::Bool && expression->getSecondOperand()->getReturnType() == storm::expressions::ExpressionReturnType::Bool) { | |||
| 							stack.push(msat_make_iff(env, leftResult, rightResult)); | |||
| 						} else { | |||
| 							stack.push(msat_make_equal(env, leftResult, rightResult)); | |||
| 						} | |||
| 						break; | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::NotEqual: | |||
| 						if (expression->getFirstOperand()->getReturnType() == storm::expressions::ExpressionReturnType::Bool && expression->getSecondOperand()->getReturnType() == storm::expressions::ExpressionReturnType::Bool) { | |||
| 							stack.push(msat_make_not(env, msat_make_iff(env, leftResult, rightResult))); | |||
| 						} else { | |||
| 							stack.push(msat_make_not(env, msat_make_equal(env, leftResult, rightResult))); | |||
| 						} | |||
| 						break; | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::Less: | |||
| 						stack.push(msat_make_and(env, msat_make_not(env, msat_make_equal(env, leftResult, rightResult)), msat_make_leq(env, leftResult, rightResult))); | |||
| 						break; | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::LessOrEqual: | |||
| 						stack.push(msat_make_leq(env, leftResult, rightResult)); | |||
| 						break; | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::Greater: | |||
| 						stack.push(msat_make_not(env, msat_make_leq(env, leftResult, rightResult))); | |||
| 						break; | |||
| 					case storm::expressions::BinaryRelationExpression::RelationType::GreaterOrEqual: | |||
| 						stack.push(msat_make_or(env, msat_make_equal(env, leftResult, rightResult), msat_make_not(env, msat_make_leq(env, leftResult, rightResult)))); | |||
| 						break; | |||
| 					default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown boolean binary operator: '" << expression->getRelationType() << "' in expression " << expression << "."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(storm::expressions::IfThenElseExpression const* expression) override { | |||
| 				expression->getCondition()->accept(this); | |||
| 				expression->getThenExpression()->accept(this); | |||
| 				expression->getElseExpression()->accept(this); | |||
| 
 | |||
| 				msat_term conditionResult = stack.top(); | |||
| 				stack.pop(); | |||
| 				msat_term thenResult = stack.top(); | |||
| 				stack.pop(); | |||
| 				msat_term elseResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				stack.push(msat_make_term_ite(env, conditionResult, thenResult, elseResult)); | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::BooleanLiteralExpression const* expression) override { | |||
| 				stack.push(expression->evaluateAsBool(nullptr) ? msat_make_true(env) : msat_make_false(env)); | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::DoubleLiteralExpression const* expression) override { | |||
| 				stack.push(msat_make_number(env, std::to_string(expression->evaluateAsDouble(nullptr)).c_str())); | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::IntegerLiteralExpression const* expression) override { | |||
| 				stack.push(msat_make_number(env, std::to_string(static_cast<int>(expression->evaluateAsInt(nullptr))).c_str())); | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::UnaryBooleanFunctionExpression const* expression) override { | |||
| 				expression->getOperand()->accept(this); | |||
| 
 | |||
| 				msat_term childResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				switch (expression->getOperatorType()) { | |||
| 					case storm::expressions::UnaryBooleanFunctionExpression::OperatorType::Not: | |||
| 						stack.push(msat_make_not(env, childResult)); | |||
| 						break; | |||
| 					default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown boolean binary operator: '" << expression->getOperatorType() << "' in expression " << expression << "."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::UnaryNumericalFunctionExpression const* expression) override { | |||
| 				expression->getOperand()->accept(this); | |||
| 
 | |||
| 				msat_term childResult = stack.top(); | |||
| 				stack.pop(); | |||
| 
 | |||
| 				switch (expression->getOperatorType()) { | |||
| 					case storm::expressions::UnaryNumericalFunctionExpression::OperatorType::Minus: | |||
| 						stack.push(msat_make_times(env, msat_make_number(env, "-1"), childResult)); | |||
| 						break; | |||
| 					default: throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown numerical unary operator: '" << expression->getOperatorType() << "'."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			virtual void visit(expressions::VariableExpression const* expression) override { | |||
| 				if (variableToDeclMap.count(expression->getVariableName()) == 0) { | |||
| 					LOG4CPLUS_ERROR(logger, "Variable " << expression->getVariableName() << " is unknown!"); | |||
| 				} | |||
| 				//LOG4CPLUS_TRACE(logger, "Variable "<<expression->getVariableName()); | |||
| 				//char* repr = msat_decl_repr(variableToDeclMap.at(expression->getVariableName())); | |||
| 				//LOG4CPLUS_TRACE(logger, "Decl: "<<repr); | |||
| 				//msat_free(repr); | |||
| 				if (MSAT_ERROR_DECL(variableToDeclMap.at(expression->getVariableName()))) { | |||
| 					LOG4CPLUS_WARN(logger, "Encountered an invalid MathSAT declaration"); | |||
| 				} | |||
| 				stack.push(msat_make_constant(env, variableToDeclMap.at(expression->getVariableName()))); | |||
| 			} | |||
| 
 | |||
| 			storm::expressions::Expression translateTerm(msat_term term) { | |||
| 				this->processTerm(term); | |||
| 
 | |||
| 				storm::expressions::Expression result = std::move(expression_stack.top()); | |||
| 				expression_stack.pop(); | |||
| 				return result; | |||
| 			} | |||
| 
 | |||
| 			void processTerm(msat_term term) { | |||
| 				if (msat_term_is_and(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult &&rightResult); | |||
| 				} else if (msat_term_is_or(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult && rightResult); | |||
| 				} else if (msat_term_is_iff(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult.iff(rightResult)); | |||
| 				} else if (msat_term_is_not(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 
 | |||
| 					storm::expressions::Expression childResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(!childResult); | |||
| 				} else if (msat_term_is_plus(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult+rightResult); | |||
| 				} else if (msat_term_is_times(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult * rightResult); | |||
| 				} else if (msat_term_is_equal(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult == rightResult); | |||
| 				} else if (msat_term_is_leq(env, term)) { | |||
| 					this->processTerm(msat_term_get_arg(term, 0)); | |||
| 					this->processTerm(msat_term_get_arg(term, 1)); | |||
| 
 | |||
| 					storm::expressions::Expression rightResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 					storm::expressions::Expression leftResult = std::move(expression_stack.top()); | |||
| 					expression_stack.pop(); | |||
| 
 | |||
| 					expression_stack.push(leftResult <= rightResult); | |||
| 				} else if (msat_term_is_true(env, term)) { | |||
| 					expression_stack.push(expressions::Expression::createTrue()); | |||
| 				} else if (msat_term_is_false(env, term)) { | |||
| 					expression_stack.push(expressions::Expression::createFalse()); | |||
| 				} else if (msat_term_is_boolean_constant(env, term)) { | |||
| 					char* name = msat_decl_get_name(msat_term_get_decl(term)); | |||
| 					std::string name_str(name); | |||
| 					expression_stack.push(expressions::Expression::createBooleanVariable(name_str.substr(0, name_str.find('/')))); | |||
| 					msat_free(name); | |||
| 				} else if (msat_term_is_constant(env, term)) { | |||
| 					char* name = msat_decl_get_name(msat_term_get_decl(term)); | |||
| 					std::string name_str(name); | |||
| 					if (msat_is_integer_type(env, msat_term_get_type(term))) { | |||
| 						expression_stack.push(expressions::Expression::createIntegerVariable(name_str.substr(0, name_str.find('/')))); | |||
| 					} else if (msat_is_rational_type(env, msat_term_get_type(term))) { | |||
| 						expression_stack.push(expressions::Expression::createDoubleVariable(name_str.substr(0, name_str.find('/')))); | |||
| 					} | |||
| 					msat_free(name); | |||
| 				} else if (msat_term_is_number(env, term)) { | |||
| 					if (msat_is_integer_type(env, msat_term_get_type(term))) { | |||
| 						expression_stack.push(expressions::Expression::createIntegerLiteral(std::stoll(msat_term_repr(term)))); | |||
| 					} else if (msat_is_rational_type(env, msat_term_get_type(term))) { | |||
| 						expression_stack.push(expressions::Expression::createDoubleLiteral(std::stod(msat_term_repr(term)))); | |||
| 					} | |||
| 				} else { | |||
| 					char* term_cstr = msat_term_repr(term); | |||
| 					std::string term_str(term_cstr); | |||
| 					msat_free(term_cstr); | |||
| 					throw storm::exceptions::ExpressionEvaluationException() << "Cannot evaluate expression: " | |||
| 						<< "Unknown term: '" << term_str << "'."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 		private: | |||
| 			msat_env& env; | |||
| 			std::stack<msat_term> stack; | |||
| 			std::stack<expressions::Expression> expression_stack; | |||
| 			std::map<std::string, msat_decl> variableToDeclMap; | |||
| 		}; | |||
| 
 | |||
| 	} // namespace adapters | |||
| } // namespace storm | |||
| 
 | |||
| #endif /* STORM_ADAPTERS_MATHSATEXPRESSIONADAPTER_H_ */ | |||
| @ -0,0 +1,321 @@ | |||
| #include "src/solver/MathSatSmtSolver.h"
 | |||
| 
 | |||
| #include <vector>
 | |||
| 
 | |||
| namespace storm { | |||
| 	namespace solver { | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 		MathSatSmtSolver::MathSatModelReference::Z3ModelReference(z3::model &m, storm::adapters::Z3ExpressionAdapter &adapter) : m_model(m), m_adapter(adapter) { | |||
| 
 | |||
| 		} | |||
| #endif
 | |||
| 
 | |||
| 		bool MathSatSmtSolver::Z3ModelReference::getBooleanValue(std::string const& name) const { | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			z3::expr z3Expr = this->m_adapter.translateExpression(storm::expressions::Expression::createBooleanVariable(name)); | |||
| 			z3::expr z3ExprValuation = m_model.eval(z3Expr, true); | |||
| 			return this->m_adapter.translateExpression(z3ExprValuation).evaluateAsBool(); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		int_fast64_t MathSatSmtSolver::Z3ModelReference::getIntegerValue(std::string const& name) const { | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			z3::expr z3Expr = this->m_adapter.translateExpression(storm::expressions::Expression::createIntegerVariable(name)); | |||
| 			z3::expr z3ExprValuation = m_model.eval(z3Expr, true); | |||
| 			return this->m_adapter.translateExpression(z3ExprValuation).evaluateAsInt(); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		MathSatSmtSolver::MathSatSmtSolver(Options options) | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			: lastCheckAssumptions(false) | |||
|             , lastResult(CheckResult::UNKNOWN) | |||
| #endif
 | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			m_cfg = msat_create_config(); | |||
| 
 | |||
| 			if (static_cast<int>(options)& static_cast<int>(Options::InterpolantComputation)) { | |||
| 				msat_res = msat_set_option(m_cfg, "interpolation", "true"); | |||
| 				if (msat_res != 0) { | |||
| 					LOG4CPLUS_WARN(logger, "MathSAT returned an error!"); | |||
| 				} | |||
| 			} | |||
| 			m_env = msat_create_env(m_cfg); | |||
| #endif
 | |||
| 		} | |||
| 		MathSatSmtSolver::~MathSatSmtSolver() { | |||
| 			msat_destroy_env(m_env); | |||
| 			msat_destroy_config(m_cfg); | |||
| 		}; | |||
| 
 | |||
| 		void MathSatSmtSolver::push() | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			msat_push_backtrack_point(m_env); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		void MathSatSmtSolver::pop() | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			msat_pop_backtrack_point(m_env); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		void MathSatSmtSolver::pop(uint_fast64_t n) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			for (uint_fast64_t i = 0; i < n; ++i) { | |||
| 				this->pop(); | |||
| 			} | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		void MathSatSmtSolver::reset() | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			msat_reset_env(m_env); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		void MathSatSmtSolver::assertExpression(storm::expressions::Expression const& e) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			msat_assert_formula(m_env, m_adapter.translateExpression(e, true)); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		SmtSolver::CheckResult MathSatSmtSolver::check() | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			lastCheckAssumptions = false; | |||
| 			switch (msat_solve(m_env)) { | |||
| 				case MSAT_SAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::SAT; | |||
| 					break; | |||
| 				case MSAT_UNSAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNSAT; | |||
| 					break; | |||
| 				default: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNKNOWN; | |||
| 					break; | |||
| 			} | |||
| 			return this->lastResult; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		SmtSolver::CheckResult MathSatSmtSolver::checkWithAssumptions(std::set<storm::expressions::Expression> const& assumptions) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			lastCheckAssumptions = true; | |||
| 			std::vector<msat_term> mathSatAssumptions; | |||
| 			mathSatAssumptions.reserve(assumptions.size()); | |||
| 
 | |||
| 			for (storm::expressions::Expression assumption : assumptions) { | |||
| 				mathSatAssumptions.push_back(this->m_adapter.translateExpression(assumption)); | |||
| 			} | |||
| 
 | |||
| 			switch (msat_solve_with_assumptions(m_env, mathSatAssumptions.data(), mathSatAssumptions.size())) { | |||
| 				case MSAT_SAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::SAT; | |||
| 					break; | |||
| 				case MSAT_UNSAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNSAT; | |||
| 					break; | |||
| 				default: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNKNOWN; | |||
| 					break; | |||
| 			} | |||
| 			return this->lastResult; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		SmtSolver::CheckResult MathSatSmtSolver::checkWithAssumptions(std::initializer_list<storm::expressions::Expression> assumptions) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			lastCheckAssumptions = true; | |||
| 			std::vector<msat_term> mathSatAssumptions; | |||
| 			mathSatAssumptions.reserve(assumptions.size()); | |||
| 
 | |||
| 			for (storm::expressions::Expression assumption : assumptions) { | |||
| 				mathSatAssumptions.push_back(this->m_adapter.translateExpression(assumption)); | |||
| 			} | |||
| 
 | |||
| 			switch (msat_solve_with_assumptions(m_env, mathSatAssumptions.data(), mathSatAssumptions.size())) { | |||
| 				case MSAT_SAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::SAT; | |||
| 					break; | |||
| 				case MSAT_UNSAT: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNSAT; | |||
| 					break; | |||
| 				default: | |||
| 					this->lastResult = SmtSolver::CheckResult::UNKNOWN; | |||
| 					break; | |||
| 			} | |||
| 			return this->lastResult; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		storm::expressions::SimpleValuation MathSatSmtSolver::getModel() | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			 | |||
| 			LOG_THROW(this->lastResult == SmtSolver::CheckResult::SAT, storm::exceptions::InvalidStateException, "Requested Model but last check result was not SAT."); | |||
| 
 | |||
| 			return this->MathSatModelToStorm(); | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 		storm::expressions::SimpleValuation MathSatSmtSolver::MathSatModelToStorm() { | |||
| 			storm::expressions::SimpleValuation stormModel; | |||
| 
 | |||
| 			msat_model_iterator model = msat_create_model_iterator(m_env); | |||
| 
 | |||
| 			while (msat_model_iterator_has_next(model)) { | |||
| 				msat_term t, v; | |||
| 				msat_model_iterator_next(model, &t, &v); | |||
| 
 | |||
| 				storm::expressions::Expression var_i_interp = this->m_adapter.translateTerm(v); | |||
| 				char* name = msat_decl_get_name(msat_term_get_decl(t)); | |||
| 
 | |||
| 				switch (var_i_interp.getReturnType()) { | |||
| 					case storm::expressions::ExpressionReturnType::Bool: | |||
| 						 | |||
| 						stormModel.addBooleanIdentifier(std::string(name), var_i_interp.evaluateAsBool()); | |||
| 						break; | |||
| 					case storm::expressions::ExpressionReturnType::Int: | |||
| 						stormModel.addIntegerIdentifier(std::string(name), var_i_interp.evaluateAsInt()); | |||
| 						break; | |||
| 					case storm::expressions::ExpressionReturnType::Double: | |||
| 						stormModel.addDoubleIdentifier(std::string(name), var_i_interp.evaluateAsDouble()); | |||
| 						break; | |||
| 					default: | |||
| 						LOG_THROW(false, storm::exceptions::ExpressionEvaluationException, "Variable interpretation in model is not of type bool, int or double.") | |||
| 							break; | |||
| 				} | |||
| 
 | |||
| 				msat_free(name); | |||
| 
 | |||
| 			} | |||
| 
 | |||
| 			return stormModel; | |||
| 		} | |||
| #endif
 | |||
| 
 | |||
| 		std::vector<storm::expressions::SimpleValuation> MathSatSmtSolver::allSat(std::vector<storm::expressions::Expression> const& important) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			 | |||
| 			std::vector<storm::expressions::SimpleValuation> valuations; | |||
| 
 | |||
| 			this->allSat(important, [&valuations](storm::expressions::SimpleValuation& valuation) -> bool {valuations.push_back(valuation); return true; }); | |||
| 
 | |||
| 			return valuations; | |||
| 
 | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 
 | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 		struct AllsatValuationsCallbackUserData { | |||
| 			msat_env env; | |||
| 			storm::adapters::MathSatExpressionAdapter &adapter; | |||
| 			storm::expressions::SimpleValuation& valuation; | |||
| 			uint_fast64_t n; | |||
| 		}; | |||
| 
 | |||
| 		int allsatValuationsCallback(msat_term *model, int size, void *user_data) { | |||
| 			AllsatValuationsCallbackUserData* user = reinterpret_cast<AllsatValuationsCallbackUserData*>(user_data); | |||
| 			++n; | |||
| 
 | |||
| 			for (int i = 0; i < size; ++i) { | |||
| 				///
 | |||
| 			} | |||
| 		} | |||
| #endif
 | |||
| 
 | |||
| 
 | |||
| 		uint_fast64_t MathSatSmtSolver::allSat(std::vector<storm::expressions::Expression> const& important, std::function<bool(storm::expressions::SimpleValuation&)> callback) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			for (storm::expressions::Expression e : important) { | |||
| 				if (!e.isVariable()) { | |||
| 					throw storm::exceptions::InvalidArgumentException() << "The important expressions for AllSat must be atoms, i.e. variable expressions."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			 | |||
| 
 | |||
| 			return numModels; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		uint_fast64_t MathSatSmtSolver::allSat(std::function<bool(SmtSolver::ModelReference&)> callback, std::vector<storm::expressions::Expression> const& important) | |||
| 		{ | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			for (storm::expressions::Expression e : important) { | |||
| 				if (!e.isVariable()) { | |||
| 					throw storm::exceptions::InvalidArgumentException() << "The important expressions for AllSat must be atoms, i.e. variable expressions."; | |||
| 				} | |||
| 			} | |||
| 
 | |||
| 			return numModels; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 
 | |||
| 		std::vector<storm::expressions::Expression> MathSatSmtSolver::getUnsatAssumptions() { | |||
| #ifdef STORM_HAVE_MSAT
 | |||
| 			if (lastResult != SmtSolver::CheckResult::UNSAT) { | |||
| 				throw storm::exceptions::InvalidStateException() << "Unsat Assumptions was called but last state is not unsat."; | |||
| 			} | |||
| 			if (!lastCheckAssumptions) { | |||
| 				throw storm::exceptions::InvalidStateException() << "Unsat Assumptions was called but last check had no assumptions."; | |||
| 			} | |||
| 
 | |||
| 			size_t numUnsatAssumpations; | |||
| 			msat_term* msatUnsatAssumptions = msat_get_unsat_assumptions(m_env, &numUnsatAssumpations); | |||
| 
 | |||
| 			std::vector<storm::expressions::Expression> unsatAssumptions; | |||
| 			unsatAssumptions.reserve(numUnsatAssumpations); | |||
| 
 | |||
| 			for (unsigned int i = 0; i < numUnsatAssumpations; ++i) { | |||
| 				unsatAssumptions.push_back(this->m_adapter.translateTerm(msatUnsatAssumptions[i])); | |||
| 			} | |||
| 
 | |||
| 			return unsatAssumptions; | |||
| #else
 | |||
| 			LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without MathSat support."); | |||
| #endif
 | |||
| 		} | |||
| 	} | |||
| } | |||
| @ -0,0 +1,84 @@ | |||
| #ifndef STORM_SOLVER_MATHSATSMTSOLVER | |||
| #define STORM_SOLVER_MATHSATSMTSOLVER | |||
| 
 | |||
| #include "storm-config.h" | |||
| #include "src/solver/SmtSolver.h" | |||
| #include "src/adapters/MathSatExpressionAdapter.h" | |||
| 
 | |||
| #ifndef STORM_HAVE_MSAT | |||
| #define STORM_HAVE_MSAT | |||
| #endif | |||
| 
 | |||
| #ifdef STORM_HAVE_MSAT | |||
| #include "mathsat.h" | |||
| #endif | |||
| 
 | |||
| namespace storm { | |||
| 	namespace solver { | |||
| 		class MathSatSmtSolver : public SmtSolver { | |||
| 		public: | |||
| 			class MathSatModelReference : public SmtSolver::ModelReference { | |||
| 			public: | |||
| #ifdef STORM_HAVE_MSAT | |||
| 				MathSatModelReference(msat_env& env, storm::adapters::MathSatExpressionAdapter &adapter); | |||
| #endif | |||
| 				virtual bool getBooleanValue(std::string const& name) const override; | |||
| 				virtual int_fast64_t getIntegerValue(std::string const& name) const override; | |||
| 			private: | |||
| #ifdef STORM_HAVE_MSAT | |||
| 				msat_env& env; | |||
| 				storm::adapters::MathSatExpressionAdapter &m_adapter; | |||
| #endif | |||
| 			}; | |||
| 		public: | |||
| 			MathSatSmtSolver(Options options = Options::ModelGeneration); | |||
| 			virtual ~MathSatSmtSolver(); | |||
| 
 | |||
| 			virtual void push() override; | |||
| 
 | |||
| 			virtual void pop() override; | |||
| 
 | |||
| 			virtual void pop(uint_fast64_t n) override; | |||
| 
 | |||
| 			virtual void reset() override; | |||
| 
 | |||
| 			virtual void assertExpression(storm::expressions::Expression const& e) override; | |||
| 
 | |||
| 			virtual CheckResult check() override; | |||
| 
 | |||
| 			virtual CheckResult checkWithAssumptions(std::set<storm::expressions::Expression> const& assumptions) override; | |||
| 
 | |||
| 			virtual CheckResult checkWithAssumptions(std::initializer_list<storm::expressions::Expression> assumptions) override; | |||
| 
 | |||
| 			virtual storm::expressions::SimpleValuation getModel() override; | |||
| 
 | |||
| 			virtual std::vector<storm::expressions::SimpleValuation> allSat(std::vector<storm::expressions::Expression> const& important) override; | |||
| 
 | |||
| 			virtual uint_fast64_t allSat(std::vector<storm::expressions::Expression> const& important, std::function<bool(storm::expressions::SimpleValuation&)> callback) override; | |||
| 
 | |||
| 			virtual uint_fast64_t allSat(std::function<bool(ModelReference&)> callback, std::vector<storm::expressions::Expression> const& important) override; | |||
| 
 | |||
| 			virtual std::vector<storm::expressions::Expression> getUnsatAssumptions() override; | |||
| 
 | |||
| 			virtual void setInterpolationGroup(uint_fast64_t group) override; | |||
| 
 | |||
| 			virtual storm::expressions::Expression getInterpolant(std::vector<uint_fast64_t> groupsA) override; | |||
| 
 | |||
| 		protected: | |||
| #ifdef STORM_HAVE_MSAT | |||
| 			virtual storm::expressions::SimpleValuation MathSatModelToStorm(); | |||
| #endif | |||
| 		private: | |||
| 
 | |||
| #ifdef STORM_HAVE_MSAT | |||
| 			msat_config m_cfg; | |||
| 			msat_env m_env; | |||
| 			storm::adapters::MathSatExpressionAdapter m_adapter; | |||
| 
 | |||
| 			bool lastCheckAssumptions; | |||
| 			CheckResult lastResult; | |||
| #endif | |||
| 		}; | |||
| 	} | |||
| } | |||
| #endif // STORM_SOLVER_MATHSATSMTSOLVER | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue