You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
10 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #ifdef STORM_HAVE_Z3
  4. #include "src/solver/Z3SmtSolver.h"
  5. TEST(Z3SmtSolver, CheckSat) {
  6. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  7. storm::expressions::Variable x = manager->declareBooleanVariable("x");
  8. storm::expressions::Variable y = manager->declareBooleanVariable("y");
  9. storm::solver::Z3SmtSolver s(*manager);
  10. storm::solver::SmtSolver::CheckResult result = storm::solver::SmtSolver::CheckResult::Unknown;
  11. storm::expressions::Expression exprDeMorgan = storm::expressions::iff(!(x && y), !x || !y);
  12. ASSERT_NO_THROW(s.add(exprDeMorgan));
  13. ASSERT_NO_THROW(result = s.check());
  14. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  15. ASSERT_NO_THROW(s.reset());
  16. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  17. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  18. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  19. storm::expressions::Expression exprFormula = a >= manager->integer(0) && a < manager->integer(5) && b > manager->integer(7) && c == (a * b) && b + a > c;
  20. ASSERT_NO_THROW(s.add(exprFormula));
  21. ASSERT_NO_THROW(result = s.check());
  22. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  23. ASSERT_NO_THROW(s.reset());
  24. }
  25. TEST(Z3SmtSolver, CheckUnsat) {
  26. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  27. storm::expressions::Variable x = manager->declareBooleanVariable("x");
  28. storm::expressions::Variable y = manager->declareBooleanVariable("y");
  29. storm::solver::Z3SmtSolver s(*manager);
  30. storm::solver::SmtSolver::CheckResult result = storm::solver::SmtSolver::CheckResult::Unknown;
  31. storm::expressions::Expression exprDeMorgan = storm::expressions::iff(!(x && y), !x || !y);
  32. ASSERT_NO_THROW(s.add(!exprDeMorgan));
  33. ASSERT_NO_THROW(result = s.check());
  34. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  35. ASSERT_NO_THROW(s.reset());
  36. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  37. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  38. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  39. storm::expressions::Expression exprFormula = a >= manager->rational(2) && a < manager->integer(5) && b > manager->integer(7) && c == (a + b + manager->integer(1)) && b + a > c;
  40. ASSERT_NO_THROW(s.add(exprFormula));
  41. ASSERT_NO_THROW(result = s.check());
  42. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  43. }
  44. TEST(Z3SmtSolver, Backtracking) {
  45. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  46. storm::solver::Z3SmtSolver s(*manager);
  47. storm::solver::SmtSolver::CheckResult result = storm::solver::SmtSolver::CheckResult::Unknown;
  48. storm::expressions::Expression expr1 = manager->boolean(true);
  49. storm::expressions::Expression expr2 = manager->boolean(false);
  50. storm::expressions::Expression expr3 = manager->boolean(false);
  51. ASSERT_NO_THROW(s.add(expr1));
  52. ASSERT_NO_THROW(result = s.check());
  53. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  54. ASSERT_NO_THROW(s.push());
  55. ASSERT_NO_THROW(s.add(expr2));
  56. ASSERT_NO_THROW(result = s.check());
  57. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  58. ASSERT_NO_THROW(s.pop());
  59. ASSERT_NO_THROW(result = s.check());
  60. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  61. ASSERT_NO_THROW(s.push());
  62. ASSERT_NO_THROW(s.add(expr2));
  63. ASSERT_NO_THROW(result = s.check());
  64. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  65. ASSERT_NO_THROW(s.push());
  66. ASSERT_NO_THROW(s.add(expr3));
  67. ASSERT_NO_THROW(result = s.check());
  68. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  69. ASSERT_NO_THROW(s.pop(2));
  70. ASSERT_NO_THROW(result = s.check());
  71. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  72. ASSERT_NO_THROW(s.reset());
  73. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  74. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  75. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  76. storm::expressions::Expression exprFormula = a >= manager->integer(0) && a < manager->integer(5) && b > manager->integer(7) && c == (a + b - manager->integer(1)) && b + a > c;
  77. storm::expressions::Expression exprFormula2 = c > a + b + manager->integer(1);
  78. ASSERT_NO_THROW(s.add(exprFormula));
  79. ASSERT_NO_THROW(result = s.check());
  80. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  81. ASSERT_NO_THROW(s.push());
  82. ASSERT_NO_THROW(s.add(exprFormula2));
  83. ASSERT_NO_THROW(result = s.check());
  84. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  85. ASSERT_NO_THROW(s.pop());
  86. ASSERT_NO_THROW(result = s.check());
  87. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  88. }
  89. TEST(Z3SmtSolver, Assumptions) {
  90. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  91. storm::solver::Z3SmtSolver s(*manager);
  92. storm::solver::SmtSolver::CheckResult result = storm::solver::SmtSolver::CheckResult::Unknown;
  93. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  94. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  95. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  96. storm::expressions::Expression exprFormula = a >= manager->integer(0) && a < manager->integer(5) && b > manager->integer(7) && c == a + b - manager->integer(1) && b + a > c;
  97. storm::expressions::Variable f2 = manager->declareBooleanVariable("f2");
  98. storm::expressions::Expression exprFormula2 = storm::expressions::implies(f2, c > a + b + manager->integer(1));
  99. ASSERT_NO_THROW(s.add(exprFormula));
  100. ASSERT_NO_THROW(result = s.check());
  101. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  102. ASSERT_NO_THROW(s.add(exprFormula2));
  103. ASSERT_NO_THROW(result = s.check());
  104. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  105. ASSERT_NO_THROW(result = s.checkWithAssumptions({f2}));
  106. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  107. ASSERT_NO_THROW(result = s.check());
  108. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  109. ASSERT_NO_THROW(result = s.checkWithAssumptions({ !f2 }));
  110. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  111. }
  112. TEST(Z3SmtSolver, GenerateModel) {
  113. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  114. storm::solver::Z3SmtSolver s(*manager);
  115. storm::solver::SmtSolver::CheckResult result;
  116. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  117. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  118. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  119. storm::expressions::Expression exprFormula = a > manager->integer(0) && a < manager->integer(5) && b > manager->integer(7) && c == a + b - manager->integer(1) && b + a > c;
  120. s.add(exprFormula);
  121. result = s.check();
  122. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Sat);
  123. std::shared_ptr<storm::solver::SmtSolver::ModelReference> model = s.getModel();
  124. int_fast64_t aEval = model->getIntegerValue(a);
  125. int_fast64_t bEval = model->getIntegerValue(b);
  126. int_fast64_t cEval = model->getIntegerValue(c);
  127. ASSERT_TRUE(cEval == aEval + bEval - 1);
  128. }
  129. TEST(Z3SmtSolver, AllSat) {
  130. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  131. storm::solver::Z3SmtSolver s(*manager);
  132. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  133. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  134. storm::expressions::Variable x = manager->declareBooleanVariable("x");
  135. storm::expressions::Variable y = manager->declareBooleanVariable("y");
  136. storm::expressions::Variable z = manager->declareBooleanVariable("z");
  137. storm::expressions::Expression exprFormula1 = storm::expressions::implies(x, a > manager->integer(5));
  138. storm::expressions::Expression exprFormula2 = storm::expressions::implies(y, a < manager->integer(5));
  139. storm::expressions::Expression exprFormula3 = storm::expressions::implies(z, b < manager->integer(5));
  140. s.add(exprFormula1);
  141. s.add(exprFormula2);
  142. s.add(exprFormula3);
  143. std::vector<storm::expressions::SimpleValuation> valuations = s.allSat({x,y});
  144. ASSERT_TRUE(valuations.size() == 3);
  145. for (int i = 0; i < valuations.size(); ++i) {
  146. ASSERT_FALSE(valuations[i].getBooleanValue(x) && valuations[i].getBooleanValue(y));
  147. for (int j = i+1; j < valuations.size(); ++j) {
  148. ASSERT_TRUE((valuations[i].getBooleanValue(x) != valuations[j].getBooleanValue(x)) || (valuations[i].getBooleanValue(y) != valuations[j].getBooleanValue(y)));
  149. }
  150. }
  151. }
  152. TEST(Z3SmtSolver, UnsatAssumptions) {
  153. std::shared_ptr<storm::expressions::ExpressionManager> manager(new storm::expressions::ExpressionManager());
  154. storm::solver::Z3SmtSolver s(*manager);
  155. storm::solver::SmtSolver::CheckResult result = storm::solver::SmtSolver::CheckResult::Unknown;
  156. storm::expressions::Variable a = manager->declareIntegerVariable("a");
  157. storm::expressions::Variable b = manager->declareIntegerVariable("b");
  158. storm::expressions::Variable c = manager->declareIntegerVariable("c");
  159. storm::expressions::Expression exprFormula = a >= manager->integer(0) && a < manager->integer(5) && b > manager->integer(7) && c == a + b - manager->integer(1) && b + a > c;
  160. storm::expressions::Variable f2 = manager->declareBooleanVariable("f2");
  161. storm::expressions::Expression exprFormula2 = storm::expressions::implies(f2, c > a + b + manager->integer(1));
  162. s.add(exprFormula);
  163. s.add(exprFormula2);
  164. result = s.checkWithAssumptions({ f2 });
  165. ASSERT_TRUE(result == storm::solver::SmtSolver::CheckResult::Unsat);
  166. std::vector<storm::expressions::Expression> unsatCore = s.getUnsatAssumptions();
  167. ASSERT_EQ(unsatCore.size(), 1);
  168. ASSERT_TRUE(unsatCore[0].isVariable());
  169. ASSERT_STREQ("f2", unsatCore[0].getIdentifier().c_str());
  170. }
  171. #endif