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.

176 lines
8.8 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #ifdef STORM_HAVE_Z3
  4. #include "z3++.h"
  5. #include "src/adapters/Z3ExpressionAdapter.h"
  6. #include "src/settings/SettingsManager.h"
  7. TEST(Z3ExpressionAdapter, StormToZ3Basic) {
  8. z3::context ctx;
  9. z3::solver s(ctx);
  10. z3::expr conjecture = ctx.bool_val(false);
  11. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  12. storm::expressions::Expression exprTrue = storm::expressions::Expression::createTrue();
  13. z3::expr z3True = ctx.bool_val(true);
  14. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprTrue), z3True)));
  15. s.add(conjecture);
  16. ASSERT_TRUE(s.check() == z3::unsat);
  17. s.reset();
  18. storm::expressions::Expression exprFalse = storm::expressions::Expression::createFalse();
  19. z3::expr z3False = ctx.bool_val(false);
  20. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprFalse), z3False)));
  21. s.add(conjecture);
  22. ASSERT_TRUE(s.check() == z3::unsat);
  23. s.reset();
  24. storm::expressions::Expression exprConjunction = (storm::expressions::Expression::createBooleanVariable("x") && storm::expressions::Expression::createBooleanVariable("y"));
  25. z3::expr z3Conjunction = (ctx.bool_const("x") && ctx.bool_const("y"));
  26. ASSERT_THROW( adapter.translateExpression(exprConjunction, false), std::out_of_range ); //variables not yet created in adapter
  27. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprConjunction, true), z3Conjunction)));
  28. s.add(conjecture);
  29. ASSERT_TRUE(s.check() == z3::unsat);
  30. s.reset();
  31. storm::expressions::Expression exprNor = !(storm::expressions::Expression::createBooleanVariable("x") || storm::expressions::Expression::createBooleanVariable("y"));
  32. z3::expr z3Nor = !(ctx.bool_const("x") || ctx.bool_const("y"));
  33. ASSERT_NO_THROW(adapter.translateExpression(exprNor, false)); //variables already created in adapter
  34. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprNor, true), z3Nor)));
  35. s.add(conjecture);
  36. ASSERT_TRUE(s.check() == z3::unsat);
  37. s.reset();
  38. }
  39. TEST(Z3ExpressionAdapter, StormToZ3Integer) {
  40. z3::context ctx;
  41. z3::solver s(ctx);
  42. z3::expr conjecture = ctx.bool_val(false);
  43. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  44. storm::expressions::Expression exprAdd = (storm::expressions::Expression::createIntegerVariable("x") + storm::expressions::Expression::createIntegerVariable("y") < -storm::expressions::Expression::createIntegerVariable("y"));
  45. z3::expr z3Add = (ctx.int_const("x") + ctx.int_const("y") < -ctx.int_const("y"));
  46. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprAdd, true), z3Add)));
  47. s.add(conjecture);
  48. ASSERT_TRUE(s.check() == z3::unsat);
  49. s.reset();
  50. storm::expressions::Expression exprMult = !(storm::expressions::Expression::createIntegerVariable("x") * storm::expressions::Expression::createIntegerVariable("y") == storm::expressions::Expression::createIntegerVariable("y"));
  51. z3::expr z3Mult = !(ctx.int_const("x") * ctx.int_const("y") == ctx.int_const("y"));
  52. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprMult, true), z3Mult)));
  53. s.add(conjecture);
  54. ASSERT_TRUE(s.check() == z3::unsat);
  55. s.reset();
  56. }
  57. TEST(Z3ExpressionAdapter, StormToZ3Real) {
  58. z3::context ctx;
  59. z3::solver s(ctx);
  60. z3::expr conjecture = ctx.bool_val(false);
  61. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  62. storm::expressions::Expression exprAdd = (storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createDoubleVariable("y") < -storm::expressions::Expression::createDoubleVariable("y"));
  63. z3::expr z3Add = (ctx.real_const("x") + ctx.real_const("y") < -ctx.real_const("y"));
  64. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprAdd, true), z3Add)));
  65. s.add(conjecture);
  66. ASSERT_TRUE(s.check() == z3::unsat);
  67. s.reset();
  68. storm::expressions::Expression exprMult = !(storm::expressions::Expression::createDoubleVariable("x") * storm::expressions::Expression::createDoubleVariable("y") == storm::expressions::Expression::createDoubleVariable("y"));
  69. z3::expr z3Mult = !(ctx.real_const("x") * ctx.real_const("y") == ctx.real_const("y"));
  70. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprMult, true), z3Mult)));
  71. s.add(conjecture);
  72. ASSERT_TRUE(s.check() == z3::unsat);
  73. s.reset();
  74. }
  75. TEST(Z3ExpressionAdapter, StormToZ3TypeErrors) {
  76. z3::context ctx;
  77. z3::solver s(ctx);
  78. z3::expr conjecture = ctx.bool_val(false);
  79. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  80. storm::expressions::Expression exprFail1 = (storm::expressions::Expression::createDoubleVariable("x") + storm::expressions::Expression::createIntegerVariable("y") < -storm::expressions::Expression::createDoubleVariable("y"));
  81. ASSERT_THROW(conjecture = adapter.translateExpression(exprFail1, true), storm::exceptions::InvalidTypeException);
  82. }
  83. TEST(Z3ExpressionAdapter, StormToZ3FloorCeil) {
  84. z3::context ctx;
  85. z3::solver s(ctx);
  86. z3::expr conjecture = ctx.bool_val(false);
  87. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  88. 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));
  89. z3::expr z3Floor = ctx.int_val(4) == ctx.int_const("i");
  90. //try { adapter.translateExpression(exprFloor, true); }
  91. //catch (std::exception &e) { std::cout << e.what() << std::endl; }
  92. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprFloor, true), z3Floor)));
  93. s.add(conjecture);
  94. ASSERT_TRUE(s.check() == z3::sat); //it is NOT logical equivalent
  95. s.reset();
  96. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_implies(ctx, adapter.translateExpression(exprFloor, true), z3Floor)));
  97. s.add(conjecture);
  98. ASSERT_TRUE(s.check() == z3::unsat); //it is NOT logical equivalent
  99. s.reset();
  100. 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));
  101. z3::expr z3Ceil = ctx.int_val(5) == ctx.int_const("i");
  102. //try { adapter.translateExpression(exprFloor, true); }
  103. //catch (std::exception &e) { std::cout << e.what() << std::endl; }
  104. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_iff(ctx, adapter.translateExpression(exprCeil, true), z3Ceil)));
  105. s.add(conjecture);
  106. ASSERT_TRUE(s.check() == z3::sat); //it is NOT logical equivalent
  107. s.reset();
  108. ASSERT_NO_THROW(conjecture = !z3::expr(ctx, Z3_mk_implies(ctx, adapter.translateExpression(exprCeil, true), z3Ceil)));
  109. s.add(conjecture);
  110. ASSERT_TRUE(s.check() == z3::unsat); //it is NOT logical equivalent
  111. s.reset();
  112. }
  113. TEST(Z3ExpressionAdapter, Z3ToStormBasic) {
  114. z3::context ctx;
  115. unsigned args = 2;
  116. storm::adapters::Z3ExpressionAdapter adapter(ctx, std::map<std::string, z3::expr>());
  117. z3::expr z3True = ctx.bool_val(true);
  118. storm::expressions::Expression exprTrue;
  119. exprTrue = adapter.translateExpression(z3True);
  120. ASSERT_TRUE(exprTrue.isTrue());
  121. z3::expr z3False = ctx.bool_val(false);
  122. storm::expressions::Expression exprFalse;
  123. exprFalse = adapter.translateExpression(z3False);
  124. ASSERT_TRUE(exprFalse.isFalse());
  125. z3::expr z3Conjunction = (ctx.bool_const("x") && ctx.bool_const("y"));
  126. storm::expressions::Expression exprConjunction;
  127. (exprConjunction = adapter.translateExpression(z3Conjunction));
  128. ASSERT_EQ(storm::expressions::OperatorType::And, exprConjunction.getOperator());
  129. ASSERT_TRUE(exprConjunction.getOperand(0).isVariable());
  130. ASSERT_EQ("x", exprConjunction.getOperand(0).getIdentifier());
  131. ASSERT_TRUE(exprConjunction.getOperand(1).isVariable());
  132. ASSERT_EQ("y", exprConjunction.getOperand(1).getIdentifier());
  133. z3::expr z3Nor = !(ctx.bool_const("x") || ctx.bool_const("y"));
  134. storm::expressions::Expression exprNor;
  135. (exprNor = adapter.translateExpression(z3Nor));
  136. ASSERT_EQ(storm::expressions::OperatorType::Not, exprNor.getOperator());
  137. ASSERT_EQ(storm::expressions::OperatorType::Or, exprNor.getOperand(0).getOperator());
  138. ASSERT_TRUE(exprNor.getOperand(0).getOperand(0).isVariable());
  139. ASSERT_EQ("x", exprNor.getOperand(0).getOperand(0).getIdentifier());
  140. ASSERT_TRUE(exprNor.getOperand(0).getOperand(1).isVariable());
  141. ASSERT_EQ("y", exprNor.getOperand(0).getOperand(1).getIdentifier());
  142. }
  143. #endif