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