3#include "storm-config.h"
7#ifdef STORM_HAVE_MATHSAT
21#ifdef STORM_HAVE_MATHSAT
25struct hash<msat_decl> {
26 size_t operator()(msat_decl
const& declaration)
const {
27 return hash<void*>()(declaration.repr);
33bool operator==(msat_decl decl1, msat_decl decl2);
39#ifdef STORM_HAVE_MATHSAT
41class MathsatExpressionAdapter :
public storm::expressions::ExpressionVisitor {
49 MathsatExpressionAdapter(storm::expressions::ExpressionManager& manager, msat_env& env) :
manager(
manager), env(env), variableToDeclarationMapping() {
59 msat_term translateExpression(storm::expressions::Expression
const& expression) {
60 additionalConstraints.clear();
62 if (MSAT_ERROR_TERM(result)) {
63 std::string errorMessage(msat_last_error_message(env));
64 STORM_LOG_THROW(!MSAT_ERROR_TERM(result), storm::exceptions::ExpressionEvaluationException,
65 "Could not translate expression to MathSAT's format. (Message: " << errorMessage <<
").");
77 msat_term translateExpression(storm::expressions::Variable
const& variable) {
80 auto const& variableExpressionPair = variableToDeclarationMapping.find(variable);
81 if (variableExpressionPair == variableToDeclarationMapping.end()) {
82 return msat_make_constant(env, createVariable(variable));
84 return msat_make_constant(env, variableExpressionPair->second);
87 bool hasAdditionalConstraints()
const {
88 return !additionalConstraints.empty();
94 std::vector<msat_term>
const& getAdditionalConstraints()
const {
95 return additionalConstraints;
104 storm::expressions::Variable
const& getVariable(msat_decl msatVariableDeclaration)
const {
105 auto const& declarationVariablePair = declarationToVariableMapping.find(msatVariableDeclaration);
106 STORM_LOG_ASSERT(declarationVariablePair != declarationToVariableMapping.end(),
"Unknown variable declaration.");
107 return declarationVariablePair->second;
110 std::unordered_map<storm::expressions::Variable, msat_decl>
const& getAllDeclaredVariables()
const {
111 return variableToDeclarationMapping;
114 virtual boost::any visit(storm::expressions::BinaryBooleanFunctionExpression
const& expression, boost::any
const& data)
override {
115 msat_term leftResult = boost::any_cast<msat_term>(expression.
getFirstOperand()->accept(*
this, data));
116 msat_term rightResult = boost::any_cast<msat_term>(expression.
getSecondOperand()->accept(*
this, data));
120 return msat_make_and(env, leftResult, rightResult);
122 return msat_make_or(env, leftResult, rightResult);
124 return msat_make_iff(env, leftResult, rightResult);
126 return msat_make_or(env, msat_make_not(env, leftResult), rightResult);
128 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
129 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<uint_fast64_t
>(expression.
getOperatorType())
130 <<
"' in expression " << expression <<
".");
134 virtual boost::any visit(storm::expressions::BinaryNumericalFunctionExpression
const& expression, boost::any
const& data)
override {
135 msat_term leftResult = boost::any_cast<msat_term>(expression.
getFirstOperand()->accept(*
this, data));
136 msat_term rightResult = boost::any_cast<msat_term>(expression.
getSecondOperand()->accept(*
this, data));
138 msat_term result = leftResult;
139 int_fast64_t exponent;
140 int_fast64_t modulus;
141 storm::expressions::Variable freshAuxiliaryVariable;
142 msat_term modVariable;
145 typename storm::NumberTraits<storm::GmpRationalNumber>::IntegerType gmpModulus;
148 return msat_make_plus(env, leftResult, rightResult);
150 return msat_make_plus(env, leftResult, msat_make_times(env, msat_make_number(env,
"-1"), rightResult));
152 return msat_make_times(env, leftResult, rightResult);
154 return msat_make_divide(env, leftResult, rightResult);
156 return msat_make_term_ite(env, msat_make_leq(env, leftResult, rightResult), leftResult, rightResult);
158 return msat_make_term_ite(env, msat_make_leq(env, leftResult, rightResult), rightResult, leftResult);
161 STORM_LOG_THROW(exponent >= 0, storm::exceptions::ExpressionEvaluationException,
"Cannot evaluate expression with negative exponent.");
164 for (; exponent > 0; --exponent) {
165 result = msat_make_times(env, result, leftResult);
171 STORM_LOG_THROW(modulus > 0, storm::exceptions::ExpressionEvaluationException,
"Cannot evaluate expression with negative modulus.");
173 freshAuxiliaryVariable =
manager.declareFreshVariable(
manager.getIntegerType(),
true);
174 modVariable = msat_make_constant(env, createVariable(freshAuxiliaryVariable));
176 gmpModulus =
typename storm::NumberTraits<storm::GmpRationalNumber>::IntegerType(
static_cast<unsigned>(modulus));
179 additionalConstraints.push_back(msat_make_int_modular_congruence(env, gmpModulus.get_mpz_t(), modVariable, leftResult));
182 lower = msat_make_number(env,
"-1");
183 upper = msat_make_number(env, std::to_string(modulus - 1).c_str());
184 additionalConstraints.push_back(
185 msat_make_and(env, msat_make_not(env, msat_make_leq(env, modVariable, lower)), msat_make_leq(env, modVariable, upper)));
188 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
189 "Cannot evaluate expression: unknown numerical binary operator '" <<
static_cast<uint_fast64_t
>(expression.
getOperatorType())
190 <<
"' in expression " << expression <<
".");
194 virtual boost::any visit(storm::expressions::BinaryRelationExpression
const& expression, boost::any
const& data)
override {
195 msat_term leftResult = boost::any_cast<msat_term>(expression.
getFirstOperand()->accept(*
this, data));
196 msat_term rightResult = boost::any_cast<msat_term>(expression.
getSecondOperand()->accept(*
this, data));
201 return msat_make_iff(env, leftResult, rightResult);
203 return msat_make_equal(env, leftResult, rightResult);
207 return msat_make_not(env, msat_make_iff(env, leftResult, rightResult));
209 return msat_make_not(env, msat_make_equal(env, leftResult, rightResult));
212 return msat_make_and(env, msat_make_not(env, msat_make_equal(env, leftResult, rightResult)), msat_make_leq(env, leftResult, rightResult));
214 return msat_make_leq(env, leftResult, rightResult);
216 return msat_make_not(env, msat_make_leq(env, leftResult, rightResult));
218 return msat_make_or(env, msat_make_equal(env, leftResult, rightResult), msat_make_not(env, msat_make_leq(env, leftResult, rightResult)));
220 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
221 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<uint_fast64_t
>(expression.
getRelationType())
222 <<
"' in expression " << expression <<
".");
226 virtual boost::any visit(storm::expressions::IfThenElseExpression
const& expression, boost::any
const& data)
override {
227 msat_term conditionResult = boost::any_cast<msat_term>(expression.
getCondition()->accept(*
this, data));
228 msat_term thenResult = boost::any_cast<msat_term>(expression.
getThenExpression()->accept(*
this, data));
229 msat_term elseResult = boost::any_cast<msat_term>(expression.
getElseExpression()->accept(*
this, data));
233 return msat_make_and(env, msat_make_or(env, msat_make_not(env, conditionResult), thenResult), msat_make_or(env, conditionResult, elseResult));
235 return msat_make_term_ite(env, conditionResult, thenResult, elseResult);
239 virtual boost::any visit(storm::expressions::BooleanLiteralExpression
const& expression, boost::any
const&)
override {
240 return expression.
getValue() ? msat_make_true(env) : msat_make_false(env);
243 virtual boost::any visit(storm::expressions::RationalLiteralExpression
const& expression, boost::any
const&)
override {
244 std::stringstream fractionStream;
245 fractionStream << expression.
getValue();
246 return msat_make_number(env, fractionStream.str().c_str());
249 virtual boost::any visit(storm::expressions::IntegerLiteralExpression
const& expression, boost::any
const&)
override {
250 return msat_make_number(env, std::to_string(
static_cast<int>(expression.
getValue())).c_str());
253 virtual boost::any visit(storm::expressions::UnaryBooleanFunctionExpression
const& expression, boost::any
const& data)
override {
254 msat_term childResult = boost::any_cast<msat_term>(expression.
getOperand()->accept(*
this, data));
258 return msat_make_not(env, childResult);
261 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
262 "Cannot evaluate expression: unknown boolean unary operator: '" <<
static_cast<uint_fast64_t
>(expression.
getOperatorType())
263 <<
"' in expression " << expression <<
".");
267 virtual boost::any visit(storm::expressions::UnaryNumericalFunctionExpression
const& expression, boost::any
const& data)
override {
268 msat_term childResult = boost::any_cast<msat_term>(expression.
getOperand()->accept(*
this, data));
272 return msat_make_times(env, msat_make_number(env,
"-1"), childResult);
274 return msat_make_floor(env, childResult);
277 return msat_make_times(env, msat_make_number(env,
"-1"), msat_make_floor(env, msat_make_times(env, msat_make_number(env,
"-1"), childResult)));
279 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
280 "Cannot evaluate expression: unknown numerical unary operator: '" <<
static_cast<uint_fast64_t
>(expression.
getOperatorType())
281 <<
"' in expression " << expression <<
".");
285 virtual boost::any visit(storm::expressions::VariableExpression
const& expression, boost::any
const&)
override {
286 return translateExpression(expression.
getVariable());
289 storm::expressions::Expression translateExpression(msat_term
const& term) {
290 if (msat_term_is_and(env, term)) {
291 return translateExpression(msat_term_get_arg(term, 0)) && translateExpression(msat_term_get_arg(term, 1));
292 }
else if (msat_term_is_or(env, term)) {
293 return translateExpression(msat_term_get_arg(term, 0)) || translateExpression(msat_term_get_arg(term, 1));
294 }
else if (msat_term_is_iff(env, term)) {
295 return storm::expressions::iff(translateExpression(msat_term_get_arg(term, 0)), translateExpression(msat_term_get_arg(term, 1)));
296 }
else if (msat_term_is_not(env, term)) {
297 return !translateExpression(msat_term_get_arg(term, 0));
298 }
else if (msat_term_is_plus(env, term)) {
299 return translateExpression(msat_term_get_arg(term, 0)) + translateExpression(msat_term_get_arg(term, 1));
300 }
else if (msat_term_is_times(env, term)) {
301 return translateExpression(msat_term_get_arg(term, 0)) * translateExpression(msat_term_get_arg(term, 1));
302 }
else if (msat_term_is_equal(env, term)) {
303 return translateExpression(msat_term_get_arg(term, 0)) == translateExpression(msat_term_get_arg(term, 1));
304 }
else if (msat_term_is_leq(env, term)) {
305 return translateExpression(msat_term_get_arg(term, 0)) <= translateExpression(msat_term_get_arg(term, 1));
306 }
else if (msat_term_is_true(env, term)) {
308 }
else if (msat_term_is_false(env, term)) {
310 }
else if (msat_term_is_constant(env, term)) {
311 char* name = msat_decl_get_name(msat_term_get_decl(term));
312 std::string nameString(name);
313 storm::expressions::Expression result =
manager.getVariableExpression(nameString.substr(0, nameString.find(
'/')));
316 }
else if (msat_term_is_number(env, term)) {
317 char* termAsCString = msat_term_repr(term);
318 std::string termString(termAsCString);
319 msat_free(termAsCString);
320 if (msat_is_integer_type(env, msat_term_get_type(term))) {
321 return manager.integer(std::stoll(msat_term_repr(term)));
322 }
else if (msat_is_rational_type(env, msat_term_get_type(term))) {
325 }
else if (msat_term_is_term_ite(env, term)) {
326 return storm::expressions::ite(translateExpression(msat_term_get_arg(term, 0)), translateExpression(msat_term_get_arg(term, 1)),
327 translateExpression(msat_term_get_arg(term, 2)));
331 char* termAsCString = msat_term_repr(term);
332 std::string termString(termAsCString);
333 msat_free(termAsCString);
334 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
"Cannot translate expression: unknown term: '" << termString <<
"'.");
343 msat_decl createVariable(storm::expressions::Variable
const& variable) {
344 msat_decl msatDeclaration;
346 msatDeclaration = msat_declare_function(env, variable.
getName().c_str(), msat_get_bool_type(env));
348 msatDeclaration = msat_declare_function(env, variable.
getName().c_str(), msat_get_integer_type(env));
350 msatDeclaration = msat_declare_function(env, variable.
getName().c_str(), msat_get_bv_type(env, variable.
getType().
getWidth()));
352 msatDeclaration = msat_declare_function(env, variable.
getName().c_str(), msat_get_rational_type(env));
355 "Encountered variable '" << variable.
getName() <<
"' with unknown type while trying to create solver variables.");
357 variableToDeclarationMapping.insert(std::make_pair(variable, msatDeclaration));
358 declarationToVariableMapping.insert(std::make_pair(msatDeclaration, variable));
359 return msatDeclaration;
363 storm::expressions::ExpressionManager&
manager;
370 std::vector<msat_term> additionalConstraints;
373 std::unordered_map<storm::expressions::Variable, msat_decl> variableToDeclarationMapping;
376 std::unordered_map<msat_decl, storm::expressions::Variable> declarationToVariableMapping;
virtual boost::any accept(ExpressionVisitor &visitor, boost::any const &data) const =0
Accepts the given visitor by calling its visit method.
OperatorType getOperatorType() const
Retrieves the operator associated with the expression.
std::shared_ptr< BaseExpression const > const & getSecondOperand() const
Retrieves the second operand of the expression.
std::shared_ptr< BaseExpression const > const & getFirstOperand() const
Retrieves the first operand of the expression.
OperatorType getOperatorType() const
Retrieves the operator associated with the expression.
RelationType getRelationType() const
Retrieves the relation associated with the expression.
bool getValue() const
Retrieves the value of the boolean literal.
BaseExpression const & getBaseExpression() const
Retrieves the base expression underlying this expression object.
std::shared_ptr< BaseExpression const > getElseExpression() const
Retrieves the else expression of the if-then-else expression.
std::shared_ptr< BaseExpression const > getCondition() const
Retrieves the condition expression of the if-then-else expression.
std::shared_ptr< BaseExpression const > getThenExpression() const
Retrieves the then expression of the if-then-else expression.
int_fast64_t getValue() const
Retrieves the value of the integer literal.
storm::RationalNumber getValue() const
Retrieves the value of the double literal.
bool isBooleanType() const
Checks whether this type is a boolean type.
std::size_t getWidth() const
Retrieves the bit width of the type, provided that it is a bitvector type.
bool isIntegerType() const
Checks whether this type is an integral type.
bool isRationalType() const
Checks whether this type is a rational type.
bool isBitVectorType() const
Checks whether this type is a bitvector type.
OperatorType getOperatorType() const
Retrieves the operator associated with this expression.
virtual std::shared_ptr< BaseExpression const > getOperand(uint_fast64_t operandIndex) const override
Retrieves the given operand from the expression.
OperatorType getOperatorType() const
Retrieves the operator associated with this expression.
Variable const & getVariable() const
Retrieves the variable associated with this expression.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this variable.
Type const & getType() const
Retrieves the type of the variable.
std::string const & getName() const
Retrieves the name of the variable.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
bool operator==(BEColourClass< ValueType > const &lhs, BEColourClass< ValueType > const &rhs)
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
Expression iff(Expression const &first, Expression const &second)
SettingsManager const & manager()
Retrieves the settings manager.
TargetType convertNumber(SourceType const &number)