Browse Source
Merge branch 'master' of https://sselab.de/lab9/private/git/storm into philippTopologicalRevival
Merge branch 'master' of https://sselab.de/lab9/private/git/storm into philippTopologicalRevival
Former-commit-id: ff3bcbc189
main
45 changed files with 1785 additions and 585 deletions
-
58src/adapters/ExplicitModelAdapter.h
-
387src/adapters/Z3ExpressionAdapter.h
-
185src/counterexamples/SMTMinimalCommandSetGenerator.h
-
8src/exceptions/ExceptionMacros.h
-
6src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h
-
2src/models/MarkovAutomaton.h
-
4src/models/Mdp.h
-
287src/parser/ExpressionParser.cpp
-
153src/parser/ExpressionParser.h
-
3src/parser/MarkovAutomatonSparseTransitionParser.cpp
-
4src/parser/PrismParser.cpp
-
2src/parser/PrismParser.h
-
190src/solver/SmtSolver.h
-
266src/solver/Z3SmtSolver.cpp
-
61src/solver/Z3SmtSolver.h
-
4src/storage/SparseMatrix.cpp
-
10src/storage/expressions/BaseExpression.h
-
23src/storage/expressions/BinaryExpression.cpp
-
5src/storage/expressions/BinaryExpression.h
-
6src/storage/expressions/BooleanLiteralExpression.cpp
-
3src/storage/expressions/BooleanLiteralExpression.h
-
6src/storage/expressions/DoubleLiteralExpression.cpp
-
3src/storage/expressions/DoubleLiteralExpression.h
-
19src/storage/expressions/Expression.cpp
-
13src/storage/expressions/Expression.h
-
29src/storage/expressions/IfThenElseExpression.cpp
-
3src/storage/expressions/IfThenElseExpression.h
-
14src/storage/expressions/IntegerLiteralExpression.cpp
-
3src/storage/expressions/IntegerLiteralExpression.h
-
33src/storage/expressions/OperatorType.cpp
-
4src/storage/expressions/OperatorType.h
-
6src/storage/expressions/SimpleValuation.cpp
-
4src/storage/expressions/TypeCheckVisitor.cpp
-
12src/storage/expressions/UnaryExpression.cpp
-
3src/storage/expressions/UnaryExpression.h
-
8src/storage/expressions/VariableExpression.cpp
-
4src/storage/expressions/VariableExpression.h
-
6src/storm.cpp
-
56src/utility/PrismUtility.h
-
4src/utility/vector.h
-
177test/functional/adapter/Z3ExpressionAdapterTest.cpp
-
2test/functional/parser/PrismParserTest.cpp
-
34test/functional/solver/GlpkLpSolverTest.cpp
-
34test/functional/solver/GurobiLpSolverTest.cpp
-
226test/functional/solver/Z3SmtSolverTest.cpp
@ -0,0 +1,190 @@ |
|||
#ifndef STORM_SOLVER_SMTSOLVER |
|||
#define STORM_SOLVER_SMTSOLVER |
|||
|
|||
#include <cstdint> |
|||
|
|||
#include "exceptions/IllegalArgumentValueException.h" |
|||
#include "exceptions/NotImplementedException.h" |
|||
#include "exceptions/IllegalArgumentTypeException.h" |
|||
#include "exceptions/IllegalFunctionCallException.h" |
|||
#include "exceptions/InvalidStateException.h" |
|||
#include "storage/expressions/Expressions.h" |
|||
#include "storage/expressions/SimpleValuation.h" |
|||
|
|||
#include <set> |
|||
#include <unordered_set> |
|||
#include <initializer_list> |
|||
#include <functional> |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
/*! |
|||
* An interface that captures the functionality of an SMT solver. |
|||
*/ |
|||
class SmtSolver { |
|||
public: |
|||
//! Option flags for smt solvers. |
|||
enum class Options { |
|||
ModelGeneration = 0x01, |
|||
UnsatCoreComputation = 0x02, |
|||
InterpolantComputation = 0x04 |
|||
}; |
|||
//! possible check results |
|||
enum class CheckResult { SAT, UNSAT, UNKNOWN }; |
|||
public: |
|||
/*! |
|||
* Constructs a new smt solver with the given options. |
|||
* |
|||
* @param options the options for the solver |
|||
* @throws storm::exceptions::IllegalArgumentValueException if an option is unsupported for the solver |
|||
*/ |
|||
SmtSolver(Options options = Options::ModelGeneration) {}; |
|||
virtual ~SmtSolver() {}; |
|||
|
|||
SmtSolver(const SmtSolver&) = delete; |
|||
SmtSolver(const SmtSolver&&) {}; |
|||
|
|||
//! pushes a backtrackingpoint in the solver |
|||
virtual void push() = 0; |
|||
//! pops a backtrackingpoint in the solver |
|||
virtual void pop() = 0; |
|||
//! pops multiple backtrack points |
|||
//! @param n number of backtrackingpoint to pop |
|||
virtual void pop(uint_fast64_t n) = 0; |
|||
//! removes all assertions |
|||
virtual void reset() = 0; |
|||
|
|||
|
|||
//! assert an expression in the solver |
|||
//! @param e the asserted expression, the return type has to be bool |
|||
//! @throws IllegalArgumentTypeException if the return type of the expression is not bool |
|||
virtual void assertExpression(storm::expressions::Expression const& e) = 0; |
|||
//! assert a set of expressions in the solver |
|||
//! @param es the asserted expressions |
|||
//! @see assert(storm::expressions::Expression &e) |
|||
virtual void assertExpression(std::set<storm::expressions::Expression> const& es) { |
|||
for (storm::expressions::Expression e : es) { |
|||
this->assertExpression(e); |
|||
} |
|||
} |
|||
//! assert a set of expressions in the solver |
|||
//! @param es the asserted expressions |
|||
//! @see assert(storm::expressions::Expression &e) |
|||
/* std::hash unavailable for expressions |
|||
virtual void assertExpression(std::unordered_set<storm::expressions::Expression> &es) { |
|||
for (storm::expressions::Expression e : es) { |
|||
this->assertExpression(e); |
|||
} |
|||
}*/ |
|||
//! assert a set of expressions in the solver |
|||
//! @param es the asserted expressions |
|||
//! @see assert(storm::expressions::Expression &e) |
|||
virtual void assertExpression(std::initializer_list<storm::expressions::Expression> const& es) { |
|||
for (storm::expressions::Expression e : es) { |
|||
this->assertExpression(e); |
|||
} |
|||
} |
|||
|
|||
/*! |
|||
* check satisfiability of the conjunction of the currently asserted expressions |
|||
* |
|||
* @returns CheckResult::SAT if the conjunction of the asserted expressions is satisfiable, |
|||
* CheckResult::UNSAT if it is unsatisfiable and CheckResult::UNKNOWN if the solver |
|||
* could not determine satisfiability |
|||
*/ |
|||
virtual CheckResult check() = 0; |
|||
//! check satisfiability of the conjunction of the currently asserted expressions and the provided assumptions |
|||
//! @param es the asserted expressions |
|||
//! @throws IllegalArgumentTypeException if the return type of one of the expressions is not bool |
|||
//! @see check() |
|||
virtual CheckResult checkWithAssumptions(std::set<storm::expressions::Expression> const& assumptions) = 0; |
|||
//! check satisfiability of the conjunction of the currently asserted expressions and the provided assumptions |
|||
//! @param es the asserted expressions |
|||
//! @throws IllegalArgumentTypeException if the return type of one of the expressions is not bool |
|||
//! @see check() |
|||
/* std::hash unavailable for expressions |
|||
virtual CheckResult checkWithAssumptions(std::unordered_set<storm::expressions::Expression> &assumptions) = 0; |
|||
*/ |
|||
//! check satisfiability of the conjunction of the currently asserted expressions and the provided assumptions |
|||
//! @param es the asserted expressions |
|||
//! @throws IllegalArgumentTypeException if the return type of one of the expressions is not bool |
|||
//! @see check() |
|||
virtual CheckResult checkWithAssumptions(std::initializer_list<storm::expressions::Expression> assumptions) = 0; |
|||
|
|||
/*! |
|||
* Gets a model for the assertion stack (and possibly assumtions) for the last call to ::check or ::checkWithAssumptions if that call |
|||
* returned CheckResult::SAT. Otherwise an exception is thrown. |
|||
* @remark Note that this function may throw an exception if it is not called immediately after a call to::check or ::checkWithAssumptions |
|||
* that returned CheckResult::SAT depending on the implementation. |
|||
* @throws InvalidStateException if no model is available |
|||
* @throws IllegalFunctionCallException if model generation is not configured for this solver |
|||
* @throws NotImplementedException if model generation is not implemented with this solver class |
|||
*/ |
|||
virtual storm::expressions::SimpleValuation getModel() { |
|||
throw storm::exceptions::NotImplementedException("This subclass of SmtSolver does not support model generation."); |
|||
} |
|||
|
|||
/*! |
|||
* Performs all AllSat over the important atoms. All valuations of the important atoms such that the currently asserted formulas are satisfiable |
|||
* are returned from the function. |
|||
* |
|||
* @warning If infinitely many valuations exist, such that the currently asserted formulas are satisfiable, this function will never return! |
|||
* |
|||
* @param important A set of expressions over which to perform all sat. |
|||
* |
|||
* @returns the set of all valuations of the important atoms, such that the currently asserted formulas are satisfiable |
|||
* |
|||
* @throws IllegalFunctionCallException if model generation is not configured for this solver |
|||
* @throws NotImplementedException if model generation is not implemented with this solver class |
|||
*/ |
|||
virtual std::vector<storm::expressions::SimpleValuation> allSat(std::vector<storm::expressions::Expression> const& important) { |
|||
throw storm::exceptions::NotImplementedException("This subclass of SmtSolver does not support model generation."); |
|||
} |
|||
|
|||
/*! |
|||
* Performs all AllSat over the important atoms. Once a valuation of the important atoms such that the currently asserted formulas are satisfiable |
|||
* is found the callback is called with that valuation. |
|||
* |
|||
* @param important A set of expressions over which to perform all sat. |
|||
* @param callback A function to call for each found valuation. |
|||
* |
|||
* @returns the number of valuations of the important atoms, such that the currently asserted formulas are satisfiable that where found |
|||
* |
|||
* @throws IllegalFunctionCallException if model generation is not configured for this solver |
|||
* @throws NotImplementedException if model generation is not implemented with this solver class |
|||
*/ |
|||
virtual uint_fast64_t allSat(std::vector<storm::expressions::Expression> const& important, std::function<bool(storm::expressions::SimpleValuation&)> callback) { |
|||
throw storm::exceptions::NotImplementedException("This subclass of SmtSolver does not support model generation."); |
|||
} |
|||
|
|||
/*! |
|||
* Retrieves the unsat core of the last call to check() |
|||
* |
|||
* @returns a subset of the asserted formulas s.t. this subset is unsat |
|||
* |
|||
* @throws InvalidStateException if no unsat core is available, i.e. the asserted formulas are consistent |
|||
* @throws IllegalFunctionCallException if unsat core generation is not configured for this solver |
|||
* @throws NotImplementedException if unsat core generation is not implemented with this solver class |
|||
*/ |
|||
virtual std::vector<storm::expressions::Expression> getUnsatCore() { |
|||
throw storm::exceptions::NotImplementedException("This subclass of SmtSolver does not support unsat core generation."); |
|||
} |
|||
|
|||
/*! |
|||
* Retrieves a subset of the assumptions from the last call to checkWithAssumptions(), s.t. the result is still unsatisfiable |
|||
* |
|||
* @returns a subset of the assumptions s.t. this subset of the assumptions results in unsat |
|||
* |
|||
* @throws InvalidStateException if no unsat assumptions is available, i.e. the asserted formulas are consistent |
|||
* @throws IllegalFunctionCallException if unsat assumptions generation is not configured for this solver |
|||
* @throws NotImplementedException if unsat assumptions generation is not implemented with this solver class |
|||
*/ |
|||
virtual std::vector<storm::expressions::Expression> getUnsatAssumptions() { |
|||
throw storm::exceptions::NotImplementedException("This subclass of SmtSolver does not support unsat core generation."); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
|
|||
#endif // STORM_SOLVER_SMTSOLVER |
@ -0,0 +1,266 @@ |
|||
#include "src/solver/Z3SmtSolver.h"
|
|||
|
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
Z3SmtSolver::Z3SmtSolver(Options options) |
|||
#ifdef STORM_HAVE_Z3
|
|||
: m_context() |
|||
, m_solver(m_context) |
|||
, m_adapter(m_context, std::map<std::string, z3::expr>()) |
|||
, lastCheckAssumptions(false) |
|||
, lastResult(CheckResult::UNKNOWN) |
|||
#endif
|
|||
{ |
|||
//intentionally left empty
|
|||
} |
|||
Z3SmtSolver::~Z3SmtSolver() {}; |
|||
|
|||
void Z3SmtSolver::push() |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
this->m_solver.push(); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
void Z3SmtSolver::pop() |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
this->m_solver.pop(); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
void Z3SmtSolver::pop(uint_fast64_t n) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
this->m_solver.pop((unsigned int)n); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
void Z3SmtSolver::reset() |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
this->m_solver.reset(); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
void Z3SmtSolver::assertExpression(storm::expressions::Expression const& e) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
this->m_solver.add(m_adapter.translateExpression(e, true)); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
SmtSolver::CheckResult Z3SmtSolver::check() |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
lastCheckAssumptions = false; |
|||
switch (this->m_solver.check()) { |
|||
case z3::sat: |
|||
this->lastResult = SmtSolver::CheckResult::SAT; |
|||
break; |
|||
case z3::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 Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
SmtSolver::CheckResult Z3SmtSolver::checkWithAssumptions(std::set<storm::expressions::Expression> const& assumptions) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
lastCheckAssumptions = true; |
|||
z3::expr_vector z3Assumptions(this->m_context); |
|||
|
|||
for (storm::expressions::Expression assumption : assumptions) { |
|||
z3Assumptions.push_back(this->m_adapter.translateExpression(assumption)); |
|||
} |
|||
|
|||
switch (this->m_solver.check(z3Assumptions)) { |
|||
case z3::sat: |
|||
this->lastResult = SmtSolver::CheckResult::SAT; |
|||
break; |
|||
case z3::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 Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
SmtSolver::CheckResult Z3SmtSolver::checkWithAssumptions(std::initializer_list<storm::expressions::Expression> assumptions) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
lastCheckAssumptions = true; |
|||
z3::expr_vector z3Assumptions(this->m_context); |
|||
|
|||
for (storm::expressions::Expression assumption : assumptions) { |
|||
z3Assumptions.push_back(this->m_adapter.translateExpression(assumption)); |
|||
} |
|||
|
|||
switch (this->m_solver.check(z3Assumptions)) { |
|||
case z3::sat: |
|||
this->lastResult = SmtSolver::CheckResult::SAT; |
|||
break; |
|||
case z3::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 Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
storm::expressions::SimpleValuation Z3SmtSolver::getModel() |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
|
|||
LOG_THROW(this->lastResult == SmtSolver::CheckResult::SAT, storm::exceptions::InvalidStateException, "Requested Model but last check result was not SAT."); |
|||
|
|||
return this->z3ModelToStorm(this->m_solver.get_model()); |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
#ifdef STORM_HAVE_Z3
|
|||
storm::expressions::SimpleValuation Z3SmtSolver::z3ModelToStorm(z3::model m) { |
|||
storm::expressions::SimpleValuation stormModel; |
|||
|
|||
for (unsigned i = 0; i < m.num_consts(); ++i) { |
|||
z3::func_decl var_i = m.get_const_decl(i); |
|||
storm::expressions::Expression var_i_interp = this->m_adapter.translateExpression(m.get_const_interp(var_i)); |
|||
|
|||
switch (var_i_interp.getReturnType()) { |
|||
case storm::expressions::ExpressionReturnType::Bool: |
|||
stormModel.addBooleanIdentifier(var_i.name().str(), var_i_interp.evaluateAsBool()); |
|||
break; |
|||
case storm::expressions::ExpressionReturnType::Int: |
|||
stormModel.addIntegerIdentifier(var_i.name().str(), var_i_interp.evaluateAsInt()); |
|||
break; |
|||
case storm::expressions::ExpressionReturnType::Double: |
|||
stormModel.addDoubleIdentifier(var_i.name().str(), 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; |
|||
} |
|||
|
|||
} |
|||
|
|||
return stormModel; |
|||
} |
|||
#endif
|
|||
|
|||
std::vector<storm::expressions::SimpleValuation> Z3SmtSolver::allSat(std::vector<storm::expressions::Expression> const& important) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
|
|||
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 Z3 support."); |
|||
#endif
|
|||
} |
|||
|
|||
uint_fast64_t Z3SmtSolver::allSat(std::vector<storm::expressions::Expression> const& important, std::function<bool(storm::expressions::SimpleValuation&)> callback) |
|||
{ |
|||
#ifdef STORM_HAVE_Z3
|
|||
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."; |
|||
} |
|||
} |
|||
|
|||
uint_fast64_t numModels = 0; |
|||
bool proceed = true; |
|||
|
|||
this->push(); |
|||
|
|||
while (proceed && this->check() == CheckResult::SAT) { |
|||
++numModels; |
|||
z3::model m = this->m_solver.get_model(); |
|||
|
|||
z3::expr modelExpr = this->m_context.bool_val(true); |
|||
storm::expressions::SimpleValuation valuation; |
|||
|
|||
for (storm::expressions::Expression importantAtom : important) { |
|||
z3::expr z3ImportantAtom = this->m_adapter.translateExpression(importantAtom); |
|||
z3::expr z3ImportantAtomValuation = m.eval(z3ImportantAtom, true); |
|||
modelExpr = modelExpr && (z3ImportantAtom == z3ImportantAtomValuation); |
|||
if (importantAtom.getReturnType() == storm::expressions::ExpressionReturnType::Bool) { |
|||
valuation.addBooleanIdentifier(importantAtom.getIdentifier(), this->m_adapter.translateExpression(z3ImportantAtomValuation).evaluateAsBool()); |
|||
} else if (importantAtom.getReturnType() == storm::expressions::ExpressionReturnType::Int) { |
|||
valuation.addIntegerIdentifier(importantAtom.getIdentifier(), this->m_adapter.translateExpression(z3ImportantAtomValuation).evaluateAsInt()); |
|||
} else if (importantAtom.getReturnType() == storm::expressions::ExpressionReturnType::Double) { |
|||
valuation.addDoubleIdentifier(importantAtom.getIdentifier(), this->m_adapter.translateExpression(z3ImportantAtomValuation).evaluateAsDouble()); |
|||
} else { |
|||
throw storm::exceptions::InvalidTypeException() << "Important atom has invalid type"; |
|||
} |
|||
} |
|||
|
|||
proceed = callback(valuation); |
|||
|
|||
this->m_solver.add(!modelExpr); |
|||
} |
|||
|
|||
this->pop(); |
|||
|
|||
return numModels; |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
std::vector<storm::expressions::Expression> Z3SmtSolver::getUnsatAssumptions() { |
|||
#ifdef STORM_HAVE_Z3
|
|||
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."; |
|||
} |
|||
|
|||
z3::expr_vector z3UnsatAssumptions = this->m_solver.unsat_core(); |
|||
|
|||
std::vector<storm::expressions::Expression> unsatAssumptions; |
|||
|
|||
for (unsigned int i = 0; i < z3UnsatAssumptions.size(); ++i) { |
|||
unsatAssumptions.push_back(this->m_adapter.translateExpression(z3UnsatAssumptions[i])); |
|||
} |
|||
|
|||
return unsatAssumptions; |
|||
#else
|
|||
LOG_THROW(false, storm::exceptions::NotImplementedException, "StoRM is compiled without Z3 support."); |
|||
#endif
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,61 @@ |
|||
#ifndef STORM_SOLVER_Z3SMTSOLVER |
|||
#define STORM_SOLVER_Z3SMTSOLVER |
|||
|
|||
#include "storm-config.h" |
|||
#include "src/solver/SmtSolver.h" |
|||
#include "src/adapters/Z3ExpressionAdapter.h" |
|||
|
|||
#ifdef STORM_HAVE_Z3 |
|||
#include "z3++.h" |
|||
#include "z3.h" |
|||
#endif |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
class Z3SmtSolver : public SmtSolver { |
|||
public: |
|||
Z3SmtSolver(Options options = Options::ModelGeneration); |
|||
virtual ~Z3SmtSolver(); |
|||
|
|||
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 std::vector<storm::expressions::Expression> getUnsatAssumptions() override; |
|||
|
|||
protected: |
|||
#ifdef STORM_HAVE_Z3 |
|||
virtual storm::expressions::SimpleValuation z3ModelToStorm(z3::model m); |
|||
#endif |
|||
private: |
|||
|
|||
#ifdef STORM_HAVE_Z3 |
|||
z3::context m_context; |
|||
z3::solver m_solver; |
|||
storm::adapters::Z3ExpressionAdapter m_adapter; |
|||
|
|||
bool lastCheckAssumptions; |
|||
CheckResult lastResult; |
|||
#endif |
|||
}; |
|||
} |
|||
} |
|||
#endif // STORM_SOLVER_Z3SMTSOLVER |
@ -0,0 +1,33 @@ |
|||
#include "src/storage/expressions/OperatorType.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
std::ostream& operator<<(std::ostream& stream, OperatorType const& operatorType) { |
|||
switch (operatorType) { |
|||
case OperatorType::And: stream << "&"; break; |
|||
case OperatorType::Or: stream << "|"; break; |
|||
case OperatorType::Xor: stream << "!="; break; |
|||
case OperatorType::Implies: stream << "=>"; break; |
|||
case OperatorType::Iff: stream << "<=>"; break; |
|||
case OperatorType::Plus: stream << "+"; break; |
|||
case OperatorType::Minus: stream << "-"; break; |
|||
case OperatorType::Times: stream << "*"; break; |
|||
case OperatorType::Divide: stream << "/"; break; |
|||
case OperatorType::Min: stream << "min"; break; |
|||
case OperatorType::Max: stream << "max"; break; |
|||
case OperatorType::Power: stream << "^"; break; |
|||
case OperatorType::Equal: stream << "="; break; |
|||
case OperatorType::NotEqual: stream << "!="; break; |
|||
case OperatorType::Less: stream << "<"; break; |
|||
case OperatorType::LessOrEqual: stream << "<="; break; |
|||
case OperatorType::Greater: stream << ">"; break; |
|||
case OperatorType::GreaterOrEqual: stream << ">="; break; |
|||
case OperatorType::Not: stream << "!"; break; |
|||
case OperatorType::Floor: stream << "floor"; break; |
|||
case OperatorType::Ceil: stream << "ceil"; break; |
|||
case OperatorType::Ite: stream << "ite"; break; |
|||
} |
|||
return stream; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,177 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#ifdef STORM_HAVE_Z3
|
|||
#include "z3++.h"
|
|||
#include "src/adapters/Z3ExpressionAdapter.h"
|
|||
#include "src/settings/Settings.h"
|
|||
|
|||
TEST(Z3ExpressionAdapter, StormToZ3Basic) { |
|||
z3::context ctx; |
|||
z3::solver s(ctx); |
|||
z3::expr conjecture = ctx.bool_val(false); |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
storm::expressions::Expression exprTrue = storm::expressions::Expression::createTrue(); |
|||
z3::expr z3True = ctx.bool_val(true); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprTrue), z3True))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
|
|||
storm::expressions::Expression exprFalse = storm::expressions::Expression::createFalse(); |
|||
z3::expr z3False = ctx.bool_val(false); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprFalse), z3False))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
|
|||
storm::expressions::Expression exprConjunction = (storm::expressions::Expression::createBooleanVariable("x") && storm::expressions::Expression::createBooleanVariable("y")); |
|||
z3::expr z3Conjunction = (ctx.bool_const("x") && ctx.bool_const("y")); |
|||
ASSERT_THROW( adapter.translateExpression(exprConjunction, false), std::out_of_range ); //variables not yet created in adapter
|
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprConjunction, true), z3Conjunction))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
|
|||
storm::expressions::Expression exprNor = !(storm::expressions::Expression::createBooleanVariable("x") || storm::expressions::Expression::createBooleanVariable("y")); |
|||
z3::expr z3Nor = !(ctx.bool_const("x") || ctx.bool_const("y")); |
|||
ASSERT_NO_THROW(adapter.translateExpression(exprNor, false)); //variables already created in adapter
|
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprNor, true), z3Nor))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
} |
|||
|
|||
TEST(Z3ExpressionAdapter, StormToZ3Integer) { |
|||
z3::context ctx; |
|||
z3::solver s(ctx); |
|||
z3::expr conjecture = ctx.bool_val(false); |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
storm::expressions::Expression exprAdd = (storm::expressions::Expression::createIntegerVariable("x") + storm::expressions::Expression::createIntegerVariable("y") < -storm::expressions::Expression::createIntegerVariable("y")); |
|||
z3::expr z3Add = (ctx.int_const("x") + ctx.int_const("y") < -ctx.int_const("y")); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprAdd, true), z3Add))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
|
|||
storm::expressions::Expression exprMult = !(storm::expressions::Expression::createIntegerVariable("x") * storm::expressions::Expression::createIntegerVariable("y") == storm::expressions::Expression::createIntegerVariable("y")); |
|||
z3::expr z3Mult = !(ctx.int_const("x") * ctx.int_const("y") == ctx.int_const("y")); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprMult, true), z3Mult))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
} |
|||
|
|||
TEST(Z3ExpressionAdapter, StormToZ3Real) { |
|||
z3::context ctx; |
|||
z3::solver s(ctx); |
|||
z3::expr conjecture = ctx.bool_val(false); |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
storm::expressions::Expression exprAdd = (storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") < -storm::expressions::Expression::createDoubleVariable("y")); |
|||
z3::expr z3Add = (ctx.real_const("x") + ctx.real_const("y") < -ctx.real_const("y")); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprAdd, true), z3Add))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
|
|||
storm::expressions::Expression exprMult = !(storm::expressions::Expression::createDoubleVariable("x") * storm::expressions::Expression::createDoubleVariable("y") == storm::expressions::Expression::createDoubleVariable("y")); |
|||
z3::expr z3Mult = !(ctx.real_const("x") * ctx.real_const("y") == ctx.real_const("y")); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprMult, true), z3Mult))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); |
|||
s.reset(); |
|||
} |
|||
|
|||
TEST(Z3ExpressionAdapter, StormToZ3TypeErrors) { |
|||
z3::context ctx; |
|||
z3::solver s(ctx); |
|||
z3::expr conjecture = ctx.bool_val(false); |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
storm::expressions::Expression exprFail1 = (storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createIntegerVariable("y") < -storm::expressions::Expression::createDoubleVariable("y")); |
|||
ASSERT_THROW(conjecture = adapter.translateExpression(exprFail1, true), storm::exceptions::InvalidTypeException); |
|||
} |
|||
|
|||
TEST(Z3ExpressionAdapter, StormToZ3FloorCeil) { |
|||
z3::context ctx; |
|||
z3::solver s(ctx); |
|||
z3::expr conjecture = ctx.bool_val(false); |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
storm::expressions::Expression exprFloor = ((storm::expressions::Expression::createDoubleVariable("d").floor()) == storm::expressions::Expression::createIntegerVariable("i") && storm::expressions::Expression::createDoubleVariable("d") > storm::expressions::Expression::createDoubleLiteral(4.1) && storm::expressions::Expression::createDoubleVariable("d") < storm::expressions::Expression::createDoubleLiteral(4.991)); |
|||
z3::expr z3Floor = ctx.int_val(4) == ctx.int_const("i"); |
|||
|
|||
//try { adapter.translateExpression(exprFloor, true); }
|
|||
//catch (std::exception &e) { std::cout << e.what() << std::endl; }
|
|||
|
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprFloor, true), z3Floor))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::sat); //it is NOT logical equivalent
|
|||
s.reset(); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_implies(ctx, adapter.translateExpression(exprFloor, true), z3Floor))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); //it is NOT logical equivalent
|
|||
s.reset(); |
|||
|
|||
|
|||
storm::expressions::Expression exprCeil = ((storm::expressions::Expression::createDoubleVariable("d").ceil()) == storm::expressions::Expression::createIntegerVariable("i") && storm::expressions::Expression::createDoubleVariable("d") > storm::expressions::Expression::createDoubleLiteral(4.1) && storm::expressions::Expression::createDoubleVariable("d") < storm::expressions::Expression::createDoubleLiteral(4.991)); |
|||
z3::expr z3Ceil = ctx.int_val(5) == ctx.int_const("i"); |
|||
|
|||
//try { adapter.translateExpression(exprFloor, true); }
|
|||
//catch (std::exception &e) { std::cout << e.what() << std::endl; }
|
|||
|
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprCeil, true), z3Ceil))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::sat); //it is NOT logical equivalent
|
|||
s.reset(); |
|||
ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_implies(ctx, adapter.translateExpression(exprCeil, true), z3Ceil))); |
|||
s.add(conjecture); |
|||
ASSERT_TRUE(s.check() == z3::unsat); //it is NOT logical equivalent
|
|||
s.reset(); |
|||
} |
|||
|
|||
TEST(Z3ExpressionAdapter, Z3ToStormBasic) { |
|||
z3::context ctx; |
|||
|
|||
unsigned args = 2; |
|||
|
|||
storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>()); |
|||
|
|||
z3::expr z3True = ctx.bool_val(true); |
|||
storm::expressions::Expression exprTrue; |
|||
exprTrue = adapter.translateExpression(z3True); |
|||
ASSERT_TRUE(exprTrue.isTrue()); |
|||
|
|||
z3::expr z3False = ctx.bool_val(false); |
|||
storm::expressions::Expression exprFalse; |
|||
exprFalse = adapter.translateExpression(z3False); |
|||
ASSERT_TRUE(exprFalse.isFalse()); |
|||
|
|||
z3::expr z3Conjunction = (ctx.bool_const("x") && ctx.bool_const("y")); |
|||
storm::expressions::Expression exprConjunction; |
|||
(exprConjunction = adapter.translateExpression(z3Conjunction)); |
|||
ASSERT_EQ(storm::expressions::OperatorType::And, exprConjunction.getOperator()); |
|||
ASSERT_TRUE(exprConjunction.getOperand(0).isVariable()); |
|||
ASSERT_EQ("x", exprConjunction.getOperand(0).getIdentifier()); |
|||
ASSERT_TRUE(exprConjunction.getOperand(1).isVariable()); |
|||
ASSERT_EQ("y", exprConjunction.getOperand(1).getIdentifier()); |
|||
|
|||
z3::expr z3Nor = !(ctx.bool_const("x") || ctx.bool_const("y")); |
|||
storm::expressions::Expression exprNor; |
|||
(exprNor = adapter.translateExpression(z3Nor)); |
|||
ASSERT_EQ(storm::expressions::OperatorType::Not, exprNor.getOperator()); |
|||
ASSERT_EQ(storm::expressions::OperatorType::Or, exprNor.getOperand(0).getOperator()); |
|||
ASSERT_TRUE(exprNor.getOperand(0).getOperand(0).isVariable()); |
|||
ASSERT_EQ("x", exprNor.getOperand(0).getOperand(0).getIdentifier()); |
|||
ASSERT_TRUE(exprNor.getOperand(0).getOperand(1).isVariable()); |
|||
ASSERT_EQ("y", exprNor.getOperand(0).getOperand(1).getIdentifier()); |
|||
} |
|||
#endif
|
@ -0,0 +1,226 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#ifdef STORM_HAVE_Z3
|
|||
#include "src/solver/Z3SmtSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
|
|||
TEST(Z3SmtSolver, CheckSat) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression exprDeMorgan = !(storm::expressions::Expression::createBooleanVariable("x") && storm::expressions::Expression::createBooleanVariable("y")).iff((!storm::expressions::Expression::createBooleanVariable("x") || !storm::expressions::Expression::createBooleanVariable("y"))); |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(exprDeMorgan)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.reset()); |
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a >= storm::expressions::Expression::createIntegerLiteral(0) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.reset()); |
|||
} |
|||
|
|||
TEST(Z3SmtSolver, CheckUnsat) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression exprDeMorgan = !(storm::expressions::Expression::createBooleanVariable("x") && storm::expressions::Expression::createBooleanVariable("y")).iff( (!storm::expressions::Expression::createBooleanVariable("x") || !storm::expressions::Expression::createBooleanVariable("y"))); |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(!exprDeMorgan)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(s.reset()); |
|||
|
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a >= storm::expressions::Expression::createIntegerLiteral(2) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
} |
|||
|
|||
|
|||
TEST(Z3SmtSolver, Backtracking) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression expr1 = storm::expressions::Expression::createTrue(); |
|||
storm::expressions::Expression expr2 = storm::expressions::Expression::createFalse(); |
|||
storm::expressions::Expression expr3 = storm::expressions::Expression::createFalse(); |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(expr1)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.push()); |
|||
ASSERT_NO_THROW(s.assertExpression(expr2)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(s.pop()); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.push()); |
|||
ASSERT_NO_THROW(s.assertExpression(expr2)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(s.push()); |
|||
ASSERT_NO_THROW(s.assertExpression(expr3)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(s.pop(2)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.reset()); |
|||
|
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a >= storm::expressions::Expression::createIntegerLiteral(0) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
storm::expressions::Expression exprFormula2 = a >= storm::expressions::Expression::createIntegerLiteral(2); |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.push()); |
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula2)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(s.pop()); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
} |
|||
|
|||
TEST(Z3SmtSolver, Assumptions) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a >= storm::expressions::Expression::createIntegerLiteral(0) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
storm::expressions::Expression f2 = storm::expressions::Expression::createBooleanVariable("f2"); |
|||
storm::expressions::Expression exprFormula2 = f2.implies(a >= storm::expressions::Expression::createIntegerLiteral(2)); |
|||
|
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(s.assertExpression(exprFormula2)); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(result = s.checkWithAssumptions({f2})); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
ASSERT_NO_THROW(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
ASSERT_NO_THROW(result = s.checkWithAssumptions({ !f2 })); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
} |
|||
|
|||
TEST(Z3SmtSolver, GenerateModel) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a > storm::expressions::Expression::createIntegerLiteral(0) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
|
|||
(s.assertExpression(exprFormula)); |
|||
(result = s.check()); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::SAT); |
|||
storm::expressions::SimpleValuation model; |
|||
(model = s.getModel()); |
|||
int_fast64_t a_eval; |
|||
(a_eval = model.getIntegerValue("a")); |
|||
ASSERT_EQ(1, a_eval); |
|||
} |
|||
|
|||
|
|||
TEST(Z3SmtSolver, AllSat) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression x = storm::expressions::Expression::createBooleanVariable("x"); |
|||
storm::expressions::Expression y = storm::expressions::Expression::createBooleanVariable("y"); |
|||
storm::expressions::Expression z = storm::expressions::Expression::createBooleanVariable("z"); |
|||
storm::expressions::Expression exprFormula1 = x.implies(a > storm::expressions::Expression::createIntegerLiteral(5)); |
|||
storm::expressions::Expression exprFormula2 = y.implies(a < storm::expressions::Expression::createIntegerLiteral(5)); |
|||
storm::expressions::Expression exprFormula3 = z.implies(b < storm::expressions::Expression::createIntegerLiteral(5)); |
|||
|
|||
(s.assertExpression(exprFormula1)); |
|||
(s.assertExpression(exprFormula2)); |
|||
(s.assertExpression(exprFormula3)); |
|||
|
|||
std::vector<storm::expressions::SimpleValuation> valuations = s.allSat({x,y}); |
|||
|
|||
ASSERT_TRUE(valuations.size() == 3); |
|||
for (int i = 0; i < valuations.size(); ++i) { |
|||
ASSERT_EQ(valuations[i].getNumberOfIdentifiers(), 2); |
|||
ASSERT_TRUE(valuations[i].containsBooleanIdentifier("x")); |
|||
ASSERT_TRUE(valuations[i].containsBooleanIdentifier("y")); |
|||
} |
|||
for (int i = 0; i < valuations.size(); ++i) { |
|||
ASSERT_FALSE(valuations[i].getBooleanValue("x") && valuations[i].getBooleanValue("y")); |
|||
|
|||
for (int j = i+1; j < valuations.size(); ++j) { |
|||
ASSERT_TRUE((valuations[i].getBooleanValue("x") != valuations[j].getBooleanValue("x")) || (valuations[i].getBooleanValue("y") != valuations[j].getBooleanValue("y"))); |
|||
} |
|||
} |
|||
} |
|||
|
|||
TEST(Z3SmtSolver, UnsatAssumptions) { |
|||
storm::solver::Z3SmtSolver s; |
|||
storm::solver::Z3SmtSolver::CheckResult result; |
|||
|
|||
storm::expressions::Expression a = storm::expressions::Expression::createIntegerVariable("a"); |
|||
storm::expressions::Expression b = storm::expressions::Expression::createIntegerVariable("b"); |
|||
storm::expressions::Expression c = storm::expressions::Expression::createIntegerVariable("c"); |
|||
storm::expressions::Expression exprFormula = a >= storm::expressions::Expression::createIntegerLiteral(0) |
|||
&& a < storm::expressions::Expression::createIntegerLiteral(5) |
|||
&& b > storm::expressions::Expression::createIntegerLiteral(7) |
|||
&& c == (a * b) |
|||
&& b + a > c; |
|||
storm::expressions::Expression f2 = storm::expressions::Expression::createBooleanVariable("f2"); |
|||
storm::expressions::Expression exprFormula2 = f2.implies(a >= storm::expressions::Expression::createIntegerLiteral(2)); |
|||
|
|||
(s.assertExpression(exprFormula)); |
|||
(s.assertExpression(exprFormula2)); |
|||
(result = s.checkWithAssumptions({ f2 })); |
|||
ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::UNSAT); |
|||
std::vector<storm::expressions::Expression> unsatCore = s.getUnsatAssumptions(); |
|||
ASSERT_EQ(unsatCore.size(), 1); |
|||
ASSERT_TRUE(unsatCore[0].isVariable()); |
|||
ASSERT_STREQ("f2", unsatCore[0].getIdentifier().c_str()); |
|||
} |
|||
#endif
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue