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))));
169 case Z3_OP_UNINTERPRETED:
171 STORM_LOG_THROW(expr.is_const(), storm::exceptions::ExpressionEvaluationException,
172 "Failed to convert Z3 expression. Encountered non-constant uninterpreted function.");
173 return manager.getVariable(expr.decl().name().str()).getExpression();
175 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
176 "Failed to convert Z3 expression. Encountered unhandled Z3_decl_kind " << expr.decl().decl_kind() <<
".");
180 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
"Failed to convert Z3 expression. Encountered unknown expression type.");
185 auto cacheIt = expressionCache.find(&expression);
186 if (cacheIt != expressionCache.end()) {
187 return cacheIt->second;
190 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
191 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
193 z3::expr result(context);
196 result = leftResult && rightResult;
199 result = leftResult || rightResult;
202 result = z3::expr(context, Z3_mk_xor(context, leftResult, rightResult));
205 result = z3::expr(context, Z3_mk_implies(context, leftResult, rightResult));
208 result = z3::expr(context, Z3_mk_iff(context, leftResult, rightResult));
211 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
212 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getOperatorType())
213 <<
"' in expression " << expression <<
".");
216 expressionCache.emplace(&expression, result);
221 auto cacheIt = expressionCache.find(&expression);
222 if (cacheIt != expressionCache.end()) {
223 return cacheIt->second;
226 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
227 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
229 z3::expr result(context);
232 result = leftResult + rightResult;
235 result = leftResult - rightResult;
238 result = leftResult * rightResult;
241 if (leftResult.is_int() && rightResult.is_int()) {
242 leftResult = z3::expr(context, Z3_mk_int2real(context, leftResult));
244 result = leftResult / rightResult;
247 result =
ite(leftResult <= rightResult, leftResult, rightResult);
250 result =
ite(leftResult >= rightResult, leftResult, rightResult);
253 result = pw(leftResult, rightResult);
256 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
257 "Cannot evaluate expression: unknown numerical binary operator '" <<
static_cast<int>(expression.
getOperatorType())
258 <<
"' in expression " << expression <<
".");
261 expressionCache.emplace(&expression, result);
266 auto cacheIt = expressionCache.find(&expression);
267 if (cacheIt != expressionCache.end()) {
268 return cacheIt->second;
271 z3::expr leftResult = boost::any_cast<z3::expr>(expression.
getFirstOperand()->accept(*
this, data));
272 z3::expr rightResult = boost::any_cast<z3::expr>(expression.
getSecondOperand()->accept(*
this, data));
274 z3::expr result(context);
277 result = leftResult == rightResult;
280 result = leftResult != rightResult;
283 result = leftResult < rightResult;
286 result = leftResult <= rightResult;
289 result = leftResult > rightResult;
292 result = leftResult >= rightResult;
295 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
296 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getRelationType())
297 <<
"' in expression " << expression <<
".");
300 expressionCache.emplace(&expression, result);
305 auto cacheIt = expressionCache.find(&expression);
306 if (cacheIt != expressionCache.end()) {
307 return cacheIt->second;
310 z3::expr result = context.bool_val(expression.
getValue());
312 expressionCache.emplace(&expression, result);
317 auto cacheIt = expressionCache.find(&expression);
318 if (cacheIt != expressionCache.end()) {
319 return cacheIt->second;
322 std::stringstream fractionStream;
323 fractionStream << expression.
getValue();
324 z3::expr result = context.real_val(fractionStream.str().c_str());
326 expressionCache.emplace(&expression, result);
331 auto cacheIt = expressionCache.find(&expression);
332 if (cacheIt != expressionCache.end()) {
333 return cacheIt->second;
336 z3::expr result = context.int_val(
static_cast<Z3_SIGNED_INTEGER
>(expression.
getValue()));
338 expressionCache.emplace(&expression, result);
343 auto cacheIt = expressionCache.find(&expression);
344 if (cacheIt != expressionCache.end()) {
345 return cacheIt->second;
348 z3::expr result = boost::any_cast<z3::expr>(expression.
getOperand()->accept(*
this, data));
355 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
356 "Cannot evaluate expression: unknown boolean binary operator '" <<
static_cast<int>(expression.
getOperatorType())
357 <<
"' in expression " << expression <<
".");
360 expressionCache.emplace(&expression, result);
365 auto cacheIt = expressionCache.find(&expression);
366 if (cacheIt != expressionCache.end()) {
367 return cacheIt->second;
370 z3::expr result = boost::any_cast<z3::expr>(expression.
getOperand()->accept(*
this, data));
378 z3::expr floorVariable = context.int_const(freshAuxiliaryVariable.
getName().c_str());
379 additionalAssertions.push_back(z3::expr(context, Z3_mk_int2real(context, floorVariable)) <= result &&
380 result < (z3::expr(context, Z3_mk_int2real(context, floorVariable)) + 1));
381 result = floorVariable;
386 z3::expr ceilVariable = context.int_const(freshAuxiliaryVariable.
getName().c_str());
387 additionalAssertions.push_back(z3::expr(context, Z3_mk_int2real(context, ceilVariable)) - 1 < result &&
388 result <= z3::expr(context, Z3_mk_int2real(context, ceilVariable)));
389 result = ceilVariable;
393 STORM_LOG_THROW(
false, storm::exceptions::ExpressionEvaluationException,
394 "Cannot evaluate expression: unknown numerical unary operator '" <<
static_cast<int>(expression.
getOperatorType()) <<
"'.");
397 expressionCache.emplace(&expression, result);
402 auto cacheIt = expressionCache.find(&expression);
403 if (cacheIt != expressionCache.end()) {
404 return cacheIt->second;
407 z3::expr conditionResult = boost::any_cast<z3::expr>(expression.
getCondition()->accept(*
this, data));
408 z3::expr thenResult = boost::any_cast<z3::expr>(expression.
getThenExpression()->accept(*
this, data));
409 z3::expr elseResult = boost::any_cast<z3::expr>(expression.
getElseExpression()->accept(*
this, data));
410 z3::expr result = z3::expr(context, Z3_mk_ite(context, conditionResult, thenResult, elseResult));
412 expressionCache.emplace(&expression, result);
417 return this->translateExpression(expression.
getVariable());
421 z3::expr z3Variable(context);
423 z3Variable = context.bool_const(variable.
getName().c_str());
425 z3Variable = context.int_const(variable.
getName().c_str());
429 z3Variable = context.real_const(variable.
getName().c_str());
432 "Encountered variable '" << variable.
getName() <<
"' with unknown type while trying to create solver variables.");
434 variableToExpressionMapping.insert(std::make_pair(variable, z3Variable));
435 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_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.