18#ifdef STORM_Z3_API_USES_STANDARD_INTEGERS
19typedef int64_t Z3_SIGNED_INTEGER;
20typedef uint64_t Z3_UNSIGNED_INTEGER;
22typedef long long Z3_SIGNED_INTEGER;
23typedef unsigned long long Z3_UNSIGNED_INTEGER;
27 :
manager(
manager), context(context), additionalAssertions(), variableToExpressionMapping() {
35 expressionCache.clear();
37 for (z3::expr
const& assertion : additionalAssertions) {
38 result = result && assertion;
40 additionalAssertions.clear();
41 return result.simplify();
47 auto const& variableExpressionPair = variableToExpressionMapping.find(variable);
48 if (variableExpressionPair == variableToExpressionMapping.end()) {
49 return createVariable(variable);
52 return variableExpressionPair->second;
56 auto const& declarationVariablePair = declarationToVariableMapping.find(z3Declaration);
57 STORM_LOG_ASSERT(declarationVariablePair != declarationToVariableMapping.end(),
"Unable to find declaration.");
58 return declarationVariablePair->second;
63 switch (expr.decl().decl_kind()) {
69 return this->translateExpression(expr.arg(0)) == this->translateExpression(expr.arg(1));
70 case Z3_OP_DISTINCT: {
71 unsigned args = expr.num_args();
72 STORM_LOG_THROW(args != 0, storm::exceptions::ExpressionEvaluationException,
73 "Failed to convert Z3 expression. DISTINCT (mutual != ) operator with 0-arity is assumed to be an error.");
78 for (
unsigned arg2 = 2; arg2 < args; ++arg2) {
79 retVal = retVal && (this->translateExpression(expr.arg(0)) != this->translateExpression(expr.arg(arg2)));
81 for (
unsigned arg1 = 1; arg1 < args; ++arg1) {
82 for (
unsigned arg2 = arg1 + 1; arg2 < args; ++arg2) {
83 retVal = retVal && (this->translateExpression(expr.arg(arg1)) != this->translateExpression(expr.arg(arg2)));
91 this->translateExpression(expr.arg(2)));
93 unsigned args = expr.num_args();
94 STORM_LOG_THROW(args != 0, storm::exceptions::ExpressionEvaluationException,
95 "Failed to convert Z3 expression. 0-ary AND is assumed to be an error.");
97 return this->translateExpression(expr.arg(0));
100 for (
unsigned i = 1;
i < args;
i++) {
101 retVal = retVal && this->translateExpression(expr.arg(i));
107 unsigned args = expr.num_args();
108 STORM_LOG_THROW(args != 0, storm::exceptions::ExpressionEvaluationException,
109 "Failed to convert Z3 expression. 0-ary OR is assumed to be an error.");
111 return this->translateExpression(expr.arg(0));
114 for (
unsigned i = 1;
i < args;
i++) {
115 retVal = retVal || this->translateExpression(expr.arg(i));
121 return storm::expressions::iff(this->translateExpression(expr.arg(0)), this->translateExpression(expr.arg(1)));
125 return !this->translateExpression(expr.arg(0));
129 return this->translateExpression(expr.arg(0)) <= this->translateExpression(expr.arg(1));
131 return this->translateExpression(expr.arg(0)) >= this->translateExpression(expr.arg(1));
133 return this->translateExpression(expr.arg(0)) < this->translateExpression(expr.arg(1));
135 return this->translateExpression(expr.arg(0)) > this->translateExpression(expr.arg(1));
137 return this->translateExpression(expr.arg(0)) + this->translateExpression(expr.arg(1));
139 return this->translateExpression(expr.arg(0)) - this->translateExpression(expr.arg(1));
141 return -this->translateExpression(expr.arg(0));
143 return this->translateExpression(expr.arg(0)) * this->translateExpression(expr.arg(1));
145 return this->translateExpression(expr.arg(0)) / this->translateExpression(expr.arg(1));
147 return this->translateExpression(expr.arg(0)) / this->translateExpression(expr.arg(1));
150 if (expr.is_int() && expr.is_const()) {
151 Z3_SIGNED_INTEGER value;
152 if (Z3_get_numeral_int64(expr.ctx(), expr, &value)) {
155 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
156 "Failed to convert Z3 expression. Expression is constant integer and value does not fit into 64-bit integer.");
159 STORM_LOG_ASSERT(expr.is_real() && expr.is_const(),
"Cannot handle numerical expression");
160 Z3_SIGNED_INTEGER num;
161 Z3_SIGNED_INTEGER den;
162 if (Z3_get_numeral_rational_int64(expr.ctx(), expr, &num, &den)) {
163 return manager.rational(storm::utility::convertNumber<storm::RationalNumber>(
static_cast<int_fast64_t
>(num)) /
164 storm::utility::convertNumber<storm::RationalNumber>(
static_cast<int_fast64_t
>(den)));
166 return manager.rational(storm::utility::convertNumber<storm::RationalNumber>(std::string(Z3_get_numeral_string(expr.ctx(), expr))));
170 STORM_LOG_WARN(
"Interpreting algebraic numbers as rational numbers. This is not an exact computation.");
172 return manager.rational(storm::utility::convertNumber<storm::RationalNumber>(
173 std::string(Z3_get_numeral_string(expr.ctx(), Z3_get_algebraic_number_lower(expr.ctx(), expr, 16)))));
174 case Z3_OP_UNINTERPRETED:
176 STORM_LOG_THROW(expr.is_const(), storm::exceptions::ExpressionEvaluationException,
177 "Failed to convert Z3 expression. Encountered non-constant uninterpreted function.");
178 return manager.getVariable(expr.decl().name().str()).getExpression();
180 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
181 "Failed to convert Z3 expression. Encountered unhandled Z3_decl_kind " << expr.decl().decl_kind() <<
".");
185 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
"Failed to convert Z3 expression. Encountered unknown expression type.");
190 auto cacheIt = expressionCache.find(&expression);
191 if (cacheIt != expressionCache.end()) {
192 return cacheIt->second;
195 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
196 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
198 z3::expr result(context);
201 result = leftResult && rightResult;
204 result = leftResult || rightResult;
207 result = z3::expr(context, Z3_mk_xor(context, leftResult, rightResult));
210 result = z3::expr(context, Z3_mk_implies(context, leftResult, rightResult));
213 result = z3::expr(context, Z3_mk_iff(context, leftResult, rightResult));
216 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
217 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getOperatorType())
218 <<
"' in expression " << expression <<
".");
221 expressionCache.emplace(&expression, result);
226 auto cacheIt = expressionCache.find(&expression);
227 if (cacheIt != expressionCache.end()) {
228 return cacheIt->second;
231 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
232 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
234 z3::expr result(context);
237 result = leftResult + rightResult;
240 result = leftResult - rightResult;
243 result = leftResult * rightResult;
246 if (leftResult.is_int() && rightResult.is_int()) {
247 leftResult = z3::expr(context, Z3_mk_int2real(context, leftResult));
249 result = leftResult / rightResult;
252 result =
ite(leftResult <= rightResult, leftResult, rightResult);
255 result =
ite(leftResult >= rightResult, leftResult, rightResult);
258 result = pw(leftResult, rightResult);
261 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
262 "Cannot evaluate expression: unknown numerical binary operator '" <<
static_cast<int>(expression.
getOperatorType())
263 <<
"' in expression " << expression <<
".");
266 expressionCache.emplace(&expression, result);
271 auto cacheIt = expressionCache.find(&expression);
272 if (cacheIt != expressionCache.end()) {
273 return cacheIt->second;
276 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
277 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
279 z3::expr result(context);
282 result = leftResult == rightResult;
285 result = leftResult != rightResult;
288 result = leftResult < rightResult;
291 result = leftResult <= rightResult;
294 result = leftResult > rightResult;
297 result = leftResult >= rightResult;
300 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
301 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getRelationType())
302 <<
"' in expression " << expression <<
".");
305 expressionCache.emplace(&expression, result);
310 auto cacheIt = expressionCache.find(&expression);
311 if (cacheIt != expressionCache.end()) {
312 return cacheIt->second;
315 z3::expr result = context.bool_val(expression.
getValue());
317 expressionCache.emplace(&expression, result);
322 auto cacheIt = expressionCache.find(&expression);
323 if (cacheIt != expressionCache.end()) {
324 return cacheIt->second;
327 std::stringstream fractionStream;
328 fractionStream << expression.
getValue();
329 z3::expr result = context.real_val(fractionStream.str().c_str());
331 expressionCache.emplace(&expression, result);
336 auto cacheIt = expressionCache.find(&expression);
337 if (cacheIt != expressionCache.end()) {
338 return cacheIt->second;
341 z3::expr result = context.int_val(
static_cast<Z3_SIGNED_INTEGER
>(expression.
getValue()));
343 expressionCache.emplace(&expression, result);
348 auto cacheIt = expressionCache.find(&expression);
349 if (cacheIt != expressionCache.end()) {
350 return cacheIt->second;
353 z3::expr result = boost::any_cast<z3::expr>(expression.
getOperand()->accept(*
this, data));
360 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
361 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getOperatorType())
362 <<
"' in expression " << expression <<
".");
365 expressionCache.emplace(&expression, result);
370 auto cacheIt = expressionCache.find(&expression);
371 if (cacheIt != expressionCache.end()) {
372 return cacheIt->second;
375 z3::expr result = boost::any_cast<z3::expr>(expression.
getOperand()->accept(*
this, data));
383 z3::expr floorVariable = context.int_const(freshAuxiliaryVariable.
getName().c_str());
384 additionalAssertions.push_back(z3::expr(context, Z3_mk_int2real(context, floorVariable)) <= result &&
385 result < (z3::expr(context, Z3_mk_int2real(context, floorVariable)) + 1));
386 result = floorVariable;
391 z3::expr ceilVariable = context.int_const(freshAuxiliaryVariable.
getName().c_str());
392 additionalAssertions.push_back(z3::expr(context, Z3_mk_int2real(context, ceilVariable)) - 1 < result &&
393 result <= z3::expr(context, Z3_mk_int2real(context, ceilVariable)));
394 result = ceilVariable;
398 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
399 "Cannot evaluate expression: unknown numerical unary operator '" <<
static_cast<int>(expression.
getOperatorType()) <<
"'.");
402 expressionCache.emplace(&expression, result);
407 auto cacheIt = expressionCache.find(&expression);
408 if (cacheIt != expressionCache.end()) {
409 return cacheIt->second;
412 z3::expr conditionResult = boost::any_cast<z3::expr>(expression.
getCondition()->accept(*
this, data));
413 z3::expr thenResult = boost::any_cast<z3::expr>(expression.
getThenExpression()->accept(*
this, data));
414 z3::expr elseResult = boost::any_cast<z3::expr>(expression.
getElseExpression()->accept(*
this, data));
415 z3::expr result = z3::expr(context, Z3_mk_ite(context, conditionResult, thenResult, elseResult));
417 expressionCache.emplace(&expression, result);
422 return this->translateExpression(expression.
getVariable());
426 z3::expr z3Variable(context);
428 z3Variable = context.bool_const(variable.
getName().c_str());
430 z3Variable = context.int_const(variable.
getName().c_str());
434 z3Variable = context.real_const(variable.
getName().c_str());
437 "Encountered variable '" << variable.
getName() <<
"' with unknown type while trying to create solver variables.");
439 variableToExpressionMapping.insert(std::make_pair(variable, z3Variable));
440 declarationToVariableMapping.insert(std::make_pair(z3Variable.decl(), variable));
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.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this expression.
This class is responsible for managing a set of typed variables and all expressions using these varia...
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_WARN(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
Expression iff(Expression const &first, Expression const &second)
Expression xclusiveor(Expression const &first, Expression const &second)
Expression implies(Expression const &first, Expression const &second)
SettingsManager const & manager()
Retrieves the settings manager.