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.

377 lines
15 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/exceptions/InvalidArgumentException.h"
  4. #include "src/storage/dd/CuddDdManager.h"
  5. #include "src/storage/dd/CuddDd.h"
  6. #include "src/storage/dd/DdMetaVariable.h"
  7. TEST(CuddDdManager, Constants) {
  8. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  9. storm::dd::Dd<storm::dd::DdType::CUDD> zero;
  10. ASSERT_NO_THROW(zero = manager->getZero());
  11. EXPECT_EQ(0, zero.getNonZeroCount());
  12. EXPECT_EQ(1, zero.getLeafCount());
  13. EXPECT_EQ(1, zero.getNodeCount());
  14. EXPECT_EQ(0, zero.getMin());
  15. EXPECT_EQ(0, zero.getMax());
  16. storm::dd::Dd<storm::dd::DdType::CUDD> one;
  17. ASSERT_NO_THROW(one = manager->getOne());
  18. EXPECT_EQ(1, one.getNonZeroCount());
  19. EXPECT_EQ(1, one.getLeafCount());
  20. EXPECT_EQ(1, one.getNodeCount());
  21. EXPECT_EQ(1, one.getMin());
  22. EXPECT_EQ(1, one.getMax());
  23. storm::dd::Dd<storm::dd::DdType::CUDD> two;
  24. ASSERT_NO_THROW(two = manager->getConstant(2));
  25. EXPECT_EQ(1, two.getNonZeroCount());
  26. EXPECT_EQ(1, two.getLeafCount());
  27. EXPECT_EQ(1, two.getNodeCount());
  28. EXPECT_EQ(2, two.getMin());
  29. EXPECT_EQ(2, two.getMax());
  30. }
  31. TEST(CuddDdManager, AddGetMetaVariableTest) {
  32. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  33. ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
  34. EXPECT_EQ(2, manager->getNumberOfMetaVariables());
  35. ASSERT_THROW(manager->addMetaVariable("x", 0, 3), storm::exceptions::InvalidArgumentException);
  36. ASSERT_NO_THROW(manager->addMetaVariable("y", 0, 3));
  37. EXPECT_EQ(4, manager->getNumberOfMetaVariables());
  38. EXPECT_TRUE(manager->hasMetaVariable("x'"));
  39. EXPECT_TRUE(manager->hasMetaVariable("y'"));
  40. std::set<std::string> metaVariableSet = {"x", "x'", "y", "y'"};
  41. EXPECT_EQ(metaVariableSet, manager->getAllMetaVariableNames());
  42. }
  43. TEST(CuddDdManager, EncodingTest) {
  44. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  45. manager->addMetaVariable("x", 1, 9);
  46. storm::dd::Dd<storm::dd::DdType::CUDD> encoding;
  47. ASSERT_THROW(encoding = manager->getEncoding("x", 0), storm::exceptions::InvalidArgumentException);
  48. ASSERT_THROW(encoding = manager->getEncoding("x", 10), storm::exceptions::InvalidArgumentException);
  49. ASSERT_NO_THROW(encoding = manager->getEncoding("x", 4));
  50. EXPECT_EQ(1, encoding.getNonZeroCount());
  51. EXPECT_EQ(6, encoding.getNodeCount());
  52. EXPECT_EQ(2, encoding.getLeafCount());
  53. }
  54. TEST(CuddDdManager, RangeTest) {
  55. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  56. ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
  57. storm::dd::Dd<storm::dd::DdType::CUDD> range;
  58. ASSERT_THROW(range = manager->getRange("y"), storm::exceptions::InvalidArgumentException);
  59. ASSERT_NO_THROW(range = manager->getRange("x"));
  60. EXPECT_EQ(9, range.getNonZeroCount());
  61. EXPECT_EQ(2, range.getLeafCount());
  62. EXPECT_EQ(6, range.getNodeCount());
  63. }
  64. TEST(CuddDdManager, IdentityTest) {
  65. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  66. manager->addMetaVariable("x", 1, 9);
  67. storm::dd::Dd<storm::dd::DdType::CUDD> range;
  68. ASSERT_THROW(range = manager->getIdentity("y"), storm::exceptions::InvalidArgumentException);
  69. ASSERT_NO_THROW(range = manager->getIdentity("x"));
  70. EXPECT_EQ(9, range.getNonZeroCount());
  71. EXPECT_EQ(10, range.getLeafCount());
  72. EXPECT_EQ(21, range.getNodeCount());
  73. }
  74. TEST(CuddDd, OperatorTest) {
  75. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  76. manager->addMetaVariable("x", 1, 9);
  77. EXPECT_TRUE(manager->getZero() == manager->getZero());
  78. EXPECT_FALSE(manager->getZero() == manager->getOne());
  79. EXPECT_FALSE(manager->getZero() != manager->getZero());
  80. EXPECT_TRUE(manager->getZero() != manager->getOne());
  81. storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne();
  82. storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getOne();
  83. storm::dd::Dd<storm::dd::DdType::CUDD> dd3 = dd1 + dd2;
  84. EXPECT_TRUE(dd3 == manager->getConstant(2));
  85. dd3 += manager->getZero();
  86. EXPECT_TRUE(dd3 == manager->getConstant(2));
  87. dd3 = dd1 && manager->getConstant(3);
  88. EXPECT_TRUE(dd1 == manager->getOne());
  89. dd3 = dd1 * manager->getConstant(3);
  90. EXPECT_TRUE(dd3 == manager->getConstant(3));
  91. dd3 *= manager->getConstant(2);
  92. EXPECT_TRUE(dd3 == manager->getConstant(6));
  93. dd3 = dd1 - dd2;
  94. EXPECT_TRUE(dd3 == manager->getZero());
  95. dd3 -= manager->getConstant(-2);
  96. EXPECT_TRUE(dd3 == manager->getConstant(2));
  97. dd3 /= manager->getConstant(2);
  98. EXPECT_TRUE(dd3 == manager->getOne());
  99. dd3.complement();
  100. EXPECT_TRUE(dd3 == manager->getZero());
  101. dd1 = !dd3;
  102. EXPECT_TRUE(dd1 == manager->getOne());
  103. dd3 = dd1 || dd2;
  104. EXPECT_TRUE(dd3 == manager->getOne());
  105. dd1 = manager->getIdentity("x");
  106. dd2 = manager->getConstant(5);
  107. dd3 = dd1.equals(dd2);
  108. EXPECT_EQ(1, dd3.getNonZeroCount());
  109. storm::dd::Dd<storm::dd::DdType::CUDD> dd4 = dd1.notEquals(dd2);
  110. EXPECT_TRUE(dd4 == !dd3);
  111. dd3 = dd1.less(dd2);
  112. EXPECT_EQ(11, dd3.getNonZeroCount());
  113. dd3 = dd1.lessOrEqual(dd2);
  114. EXPECT_EQ(12, dd3.getNonZeroCount());
  115. dd3 = dd1.greater(dd2);
  116. EXPECT_EQ(4, dd3.getNonZeroCount());
  117. dd3 = dd1.greaterOrEqual(dd2);
  118. EXPECT_EQ(5, dd3.getNonZeroCount());
  119. dd3 = (manager->getEncoding("x", 2)).ite(dd2, dd1);
  120. dd4 = dd3.less(dd2);
  121. EXPECT_EQ(10, dd4.getNonZeroCount());
  122. dd4 = dd3.minimum(dd1);
  123. dd4 *= manager->getEncoding("x", 2);
  124. dd4.sumAbstract({"x"});
  125. EXPECT_EQ(2, dd4.getValue());
  126. dd4 = dd3.maximum(dd1);
  127. dd4 *= manager->getEncoding("x", 2);
  128. dd4.sumAbstract({"x"});
  129. EXPECT_EQ(5, dd4.getValue());
  130. dd1 = manager->getConstant(0.01);
  131. dd2 = manager->getConstant(0.01 + 1e-6);
  132. EXPECT_TRUE(dd1.equalModuloPrecision(dd2, 1e-6, false));
  133. EXPECT_FALSE(dd1.equalModuloPrecision(dd2, 1e-6));
  134. }
  135. TEST(CuddDd, AbstractionTest) {
  136. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  137. manager->addMetaVariable("x", 1, 9);
  138. storm::dd::Dd<storm::dd::DdType::CUDD> dd1;
  139. storm::dd::Dd<storm::dd::DdType::CUDD> dd2;
  140. storm::dd::Dd<storm::dd::DdType::CUDD> dd3;
  141. dd1 = manager->getIdentity("x");
  142. dd2 = manager->getConstant(5);
  143. dd3 = dd1.equals(dd2);
  144. EXPECT_EQ(1, dd3.getNonZeroCount());
  145. ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
  146. ASSERT_NO_THROW(dd3.existsAbstract({"x"}));
  147. EXPECT_EQ(1, dd3.getNonZeroCount());
  148. EXPECT_EQ(1, dd3.getMax());
  149. dd3 = dd1.equals(dd2);
  150. dd3 *= manager->getConstant(3);
  151. EXPECT_EQ(1, dd3.getNonZeroCount());
  152. ASSERT_THROW(dd3.existsAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
  153. ASSERT_NO_THROW(dd3.existsAbstract({"x"}));
  154. EXPECT_TRUE(dd3 == manager->getZero());
  155. dd3 = dd1.equals(dd2);
  156. dd3 *= manager->getConstant(3);
  157. ASSERT_THROW(dd3.sumAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
  158. ASSERT_NO_THROW(dd3.sumAbstract({"x"}));
  159. EXPECT_EQ(1, dd3.getNonZeroCount());
  160. EXPECT_EQ(3, dd3.getMax());
  161. dd3 = dd1.equals(dd2);
  162. dd3 *= manager->getConstant(3);
  163. ASSERT_THROW(dd3.minAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
  164. ASSERT_NO_THROW(dd3.minAbstract({"x"}));
  165. EXPECT_EQ(0, dd3.getNonZeroCount());
  166. EXPECT_EQ(0, dd3.getMax());
  167. dd3 = dd1.equals(dd2);
  168. dd3 *= manager->getConstant(3);
  169. ASSERT_THROW(dd3.maxAbstract({"x'"}), storm::exceptions::InvalidArgumentException);
  170. ASSERT_NO_THROW(dd3.maxAbstract({"x"}));
  171. EXPECT_EQ(1, dd3.getNonZeroCount());
  172. EXPECT_EQ(3, dd3.getMax());
  173. }
  174. TEST(CuddDd, SwapTest) {
  175. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  176. manager->addMetaVariable("x", 1, 9);
  177. manager->addMetaVariable("z", 2, 8);
  178. storm::dd::Dd<storm::dd::DdType::CUDD> dd1;
  179. storm::dd::Dd<storm::dd::DdType::CUDD> dd2;
  180. dd1 = manager->getIdentity("x");
  181. ASSERT_THROW(dd1.swapVariables({std::make_pair("x", "z")}), storm::exceptions::InvalidArgumentException);
  182. ASSERT_NO_THROW(dd1.swapVariables({std::make_pair("x", "x'")}));
  183. EXPECT_TRUE(dd1 == manager->getIdentity("x'"));
  184. }
  185. TEST(CuddDd, MultiplyMatrixTest) {
  186. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  187. manager->addMetaVariable("x", 1, 9);
  188. storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getIdentity("x").equals(manager->getIdentity("x'"));
  189. storm::dd::Dd<storm::dd::DdType::CUDD> dd2 = manager->getRange("x'");
  190. storm::dd::Dd<storm::dd::DdType::CUDD> dd3;
  191. dd1 *= manager->getConstant(2);
  192. ASSERT_NO_THROW(dd3 = dd1.multiplyMatrix(dd2, {"x'"}));
  193. ASSERT_NO_THROW(dd3.swapVariables({std::make_pair("x", "x'")}));
  194. EXPECT_TRUE(dd3 == dd2 * manager->getConstant(2));
  195. }
  196. TEST(CuddDd, GetSetValueTest) {
  197. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  198. manager->addMetaVariable("x", 1, 9);
  199. storm::dd::Dd<storm::dd::DdType::CUDD> dd1 = manager->getOne();
  200. ASSERT_NO_THROW(dd1.setValue("x", 4, 2));
  201. EXPECT_EQ(2, dd1.getLeafCount());
  202. std::map<std::string, int_fast64_t> metaVariableToValueMap;
  203. metaVariableToValueMap.emplace("x", 1);
  204. EXPECT_EQ(1, dd1.getValue(metaVariableToValueMap));
  205. metaVariableToValueMap.clear();
  206. metaVariableToValueMap.emplace("x", 4);
  207. EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap));
  208. }
  209. TEST(CuddDd, ForwardIteratorTest) {
  210. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  211. manager->addMetaVariable("x", 1, 9);
  212. manager->addMetaVariable("y", 0, 3);
  213. storm::dd::Dd<storm::dd::DdType::CUDD> dd;
  214. ASSERT_NO_THROW(dd = manager->getRange("x"));
  215. storm::dd::DdForwardIterator<storm::dd::DdType::CUDD> it, ite;
  216. ASSERT_NO_THROW(it = dd.begin());
  217. ASSERT_NO_THROW(ite = dd.end());
  218. std::pair<storm::expressions::SimpleValuation, double> valuationValuePair;
  219. uint_fast64_t numberOfValuations = 0;
  220. while (it != ite) {
  221. ASSERT_NO_THROW(valuationValuePair = *it);
  222. ASSERT_NO_THROW(++it);
  223. ++numberOfValuations;
  224. }
  225. EXPECT_EQ(9, numberOfValuations);
  226. dd = manager->getRange("x");
  227. dd = dd.ite(manager->getOne(), manager->getOne());
  228. ASSERT_NO_THROW(it = dd.begin());
  229. ASSERT_NO_THROW(ite = dd.end());
  230. numberOfValuations = 0;
  231. while (it != ite) {
  232. ASSERT_NO_THROW(valuationValuePair = *it);
  233. ASSERT_NO_THROW(++it);
  234. ++numberOfValuations;
  235. }
  236. EXPECT_EQ(16, numberOfValuations);
  237. ASSERT_NO_THROW(it = dd.begin(false));
  238. ASSERT_NO_THROW(ite = dd.end());
  239. numberOfValuations = 0;
  240. while (it != ite) {
  241. ASSERT_NO_THROW(valuationValuePair = *it);
  242. ASSERT_NO_THROW(++it);
  243. ++numberOfValuations;
  244. }
  245. EXPECT_EQ(1, numberOfValuations);
  246. }
  247. TEST(CuddDd, ToExpressionTest) {
  248. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
  249. manager->addMetaVariable("x", 1, 9);
  250. storm::dd::Dd<storm::dd::DdType::CUDD> dd;
  251. ASSERT_NO_THROW(dd = manager->getIdentity("x"));
  252. storm::expressions::Expression ddAsExpression;
  253. ASSERT_NO_THROW(ddAsExpression = dd.toExpression());
  254. storm::expressions::SimpleValuation valuation;
  255. for (std::size_t bit = 0; bit < manager->getMetaVariable("x").getNumberOfDdVariables(); ++bit) {
  256. valuation.addBooleanIdentifier("x." + std::to_string(bit));
  257. }
  258. storm::dd::DdMetaVariable<storm::dd::DdType::CUDD> const& metaVariable = manager->getMetaVariable("x");
  259. for (auto valuationValuePair : dd) {
  260. for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
  261. // Check if the i-th bit is set or not and modify the valuation accordingly.
  262. if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1 << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
  263. valuation.setBooleanValue("x." + std::to_string(i), true);
  264. } else {
  265. valuation.setBooleanValue("x." + std::to_string(i), false);
  266. }
  267. }
  268. // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
  269. // same value as the current value obtained from the DD.
  270. EXPECT_EQ(valuationValuePair.second, ddAsExpression.evaluateAsDouble(&valuation));
  271. }
  272. storm::expressions::Expression mintermExpression = dd.getMintermExpression();
  273. // Check whether all minterms are covered.
  274. for (auto valuationValuePair : dd) {
  275. for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
  276. // Check if the i-th bit is set or not and modify the valuation accordingly.
  277. if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1 << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
  278. valuation.setBooleanValue("x." + std::to_string(i), true);
  279. } else {
  280. valuation.setBooleanValue("x." + std::to_string(i), false);
  281. }
  282. }
  283. // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
  284. // same value as the current value obtained from the DD.
  285. EXPECT_TRUE(mintermExpression.evaluateAsBool(&valuation));
  286. }
  287. // Now check no additional minterms are covered.
  288. dd = !dd;
  289. for (auto valuationValuePair : dd) {
  290. for (std::size_t i = 0; i < metaVariable.getNumberOfDdVariables(); ++i) {
  291. // Check if the i-th bit is set or not and modify the valuation accordingly.
  292. if (((valuationValuePair.first.getIntegerValue("x") - metaVariable.getLow()) & (1 << (metaVariable.getNumberOfDdVariables() - i - 1))) != 0) {
  293. valuation.setBooleanValue("x." + std::to_string(i), true);
  294. } else {
  295. valuation.setBooleanValue("x." + std::to_string(i), false);
  296. }
  297. }
  298. // At this point, the constructed valuation should make the expression obtained from the DD evaluate to the very
  299. // same value as the current value obtained from the DD.
  300. EXPECT_FALSE(mintermExpression.evaluateAsBool(&valuation));
  301. }
  302. }