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.

1188 lines
62 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/adapters/CarlAdapter.h"
  4. #include "src/exceptions/InvalidArgumentException.h"
  5. #include "src/storage/dd/DdManager.h"
  6. #include "src/storage/dd/Add.h"
  7. #include "src/storage/dd/Odd.h"
  8. #include "src/storage/dd/DdMetaVariable.h"
  9. #include "src/settings/SettingsManager.h"
  10. #include "src/storage/SparseMatrix.h"
  11. #include <memory>
  12. #include <iostream>
  13. TEST(SylvanDd, Constants) {
  14. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  15. storm::dd::Add<storm::dd::DdType::Sylvan, double> zero;
  16. ASSERT_NO_THROW(zero = manager->template getAddZero<double>());
  17. EXPECT_EQ(0ul, zero.getNonZeroCount());
  18. EXPECT_EQ(1ul, zero.getLeafCount());
  19. EXPECT_EQ(1ul, zero.getNodeCount());
  20. EXPECT_EQ(0, zero.getMin());
  21. EXPECT_EQ(0, zero.getMax());
  22. storm::dd::Add<storm::dd::DdType::Sylvan, double> one;
  23. ASSERT_NO_THROW(one = manager->template getAddOne<double>());
  24. EXPECT_EQ(0ul, one.getNonZeroCount());
  25. EXPECT_EQ(1ul, one.getLeafCount());
  26. EXPECT_EQ(1ul, one.getNodeCount());
  27. EXPECT_EQ(1, one.getMin());
  28. EXPECT_EQ(1, one.getMax());
  29. storm::dd::Add<storm::dd::DdType::Sylvan, double> two;
  30. ASSERT_NO_THROW(two = manager->template getConstant<double>(2));
  31. EXPECT_EQ(0ul, two.getNonZeroCount());
  32. EXPECT_EQ(1ul, two.getLeafCount());
  33. EXPECT_EQ(1ul, two.getNodeCount());
  34. EXPECT_EQ(2, two.getMin());
  35. EXPECT_EQ(2, two.getMax());
  36. }
  37. TEST(SylvanDd, BddConstants) {
  38. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  39. storm::dd::Bdd<storm::dd::DdType::Sylvan> zero;
  40. ASSERT_NO_THROW(zero = manager->getBddZero());
  41. EXPECT_EQ(0ul, zero.getNonZeroCount());
  42. EXPECT_EQ(1ul, zero.getLeafCount());
  43. EXPECT_EQ(1ul, zero.getNodeCount());
  44. storm::dd::Bdd<storm::dd::DdType::Sylvan> one;
  45. ASSERT_NO_THROW(one = manager->getBddOne());
  46. EXPECT_EQ(0ul, one.getNonZeroCount());
  47. EXPECT_EQ(1ul, one.getLeafCount());
  48. EXPECT_EQ(1ul, one.getNodeCount());
  49. }
  50. TEST(SylvanDd, BddExistAbstractRepresentative) {
  51. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  52. storm::dd::Bdd<storm::dd::DdType::Sylvan> zero;
  53. ASSERT_NO_THROW(zero = manager->getBddZero());
  54. storm::dd::Bdd<storm::dd::DdType::Sylvan> one;
  55. ASSERT_NO_THROW(one = manager->getBddOne());
  56. std::pair<storm::expressions::Variable, storm::expressions::Variable> x;
  57. std::pair<storm::expressions::Variable, storm::expressions::Variable> y;
  58. std::pair<storm::expressions::Variable, storm::expressions::Variable> z;
  59. ASSERT_NO_THROW(x = manager->addMetaVariable("x", 0, 1));
  60. ASSERT_NO_THROW(y = manager->addMetaVariable("y", 0, 1));
  61. ASSERT_NO_THROW(z = manager->addMetaVariable("z", 0, 1));
  62. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(x.first, 0);
  63. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(x.first, 1);
  64. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(y.first, 0);
  65. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(y.first, 1);
  66. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ0 = manager->getEncoding(z.first, 0);
  67. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ1 = manager->getEncoding(z.first, 1);
  68. // Abstract from FALSE
  69. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_false_x = zero.existsAbstractRepresentative({x.first});
  70. EXPECT_EQ(0ul, representative_false_x.getNonZeroCount());
  71. EXPECT_EQ(1ul, representative_false_x.getLeafCount());
  72. EXPECT_EQ(1ul, representative_false_x.getNodeCount());
  73. EXPECT_TRUE(representative_false_x == zero);
  74. // Abstract from TRUE
  75. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_x = one.existsAbstractRepresentative({x.first});
  76. EXPECT_EQ(0ul, representative_true_x.getNonZeroCount());
  77. EXPECT_EQ(1ul, representative_true_x.getLeafCount());
  78. EXPECT_EQ(2ul, representative_true_x.getNodeCount());
  79. EXPECT_TRUE(representative_true_x == bddX0);
  80. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_xyz = one.existsAbstractRepresentative({x.first, y.first, z.first});
  81. EXPECT_EQ(0ul, representative_true_xyz.getNonZeroCount());
  82. EXPECT_EQ(1ul, representative_true_xyz.getLeafCount());
  83. EXPECT_EQ(4ul, representative_true_xyz.getNodeCount());
  84. EXPECT_TRUE(representative_true_xyz == ((bddX0 && bddY0) && bddZ0));
  85. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1Y0Z0 = (bddX1 && bddY0) && bddZ0;
  86. EXPECT_EQ(1ul, bddX1Y0Z0.getNonZeroCount());
  87. EXPECT_EQ(1ul, bddX1Y0Z0.getLeafCount());
  88. EXPECT_EQ(4ul, bddX1Y0Z0.getNodeCount());
  89. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_x = bddX1Y0Z0.existsAbstractRepresentative({x.first});
  90. EXPECT_EQ(1ul, representative_x.getNonZeroCount());
  91. EXPECT_EQ(1ul, representative_x.getLeafCount());
  92. EXPECT_EQ(4ul, representative_x.getNodeCount());
  93. EXPECT_TRUE(bddX1Y0Z0 == representative_x);
  94. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_y = bddX1Y0Z0.existsAbstractRepresentative({y.first});
  95. EXPECT_EQ(1ul, representative_y.getNonZeroCount());
  96. EXPECT_EQ(1ul, representative_y.getLeafCount());
  97. EXPECT_EQ(4ul, representative_y.getNodeCount());
  98. EXPECT_TRUE(bddX1Y0Z0 == representative_y);
  99. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_z = bddX1Y0Z0.existsAbstractRepresentative({z.first});
  100. EXPECT_EQ(1ul, representative_z.getNonZeroCount());
  101. EXPECT_EQ(1ul, representative_z.getLeafCount());
  102. EXPECT_EQ(4ul, representative_z.getNodeCount());
  103. EXPECT_TRUE(bddX1Y0Z0 == representative_z);
  104. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_xyz = bddX1Y0Z0.existsAbstractRepresentative({x.first, y.first, z.first});
  105. EXPECT_EQ(1ul, representative_xyz.getNonZeroCount());
  106. EXPECT_EQ(1ul, representative_xyz.getLeafCount());
  107. EXPECT_EQ(4ul, representative_xyz.getNodeCount());
  108. EXPECT_TRUE(bddX1Y0Z0 == representative_xyz);
  109. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0Y0Z0 = (bddX0 && bddY0) && bddZ0;
  110. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1Y1Z1 = (bddX1 && bddY1) && bddZ1;
  111. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddAllTrueOrAllFalse = bddX0Y0Z0 || bddX1Y1Z1;
  112. //bddAllTrueOrAllFalse.template toAdd<double>().exportToDot("test_Sylvan_addAllTrueOrAllFalse.dot");
  113. representative_x = bddAllTrueOrAllFalse.existsAbstractRepresentative({x.first});
  114. EXPECT_EQ(2ul, representative_x.getNonZeroCount());
  115. EXPECT_EQ(1ul, representative_x.getLeafCount());
  116. EXPECT_EQ(5ul, representative_x.getNodeCount());
  117. EXPECT_TRUE(bddAllTrueOrAllFalse == representative_x);
  118. representative_y = bddAllTrueOrAllFalse.existsAbstractRepresentative({y.first});
  119. EXPECT_EQ(2ul, representative_y.getNonZeroCount());
  120. EXPECT_EQ(1ul, representative_y.getLeafCount());
  121. EXPECT_EQ(5ul, representative_y.getNodeCount());
  122. EXPECT_TRUE(bddAllTrueOrAllFalse == representative_y);
  123. representative_z = bddAllTrueOrAllFalse.existsAbstractRepresentative({z.first});
  124. EXPECT_EQ(2ul, representative_z.getNonZeroCount());
  125. EXPECT_EQ(1ul, representative_z.getLeafCount());
  126. EXPECT_EQ(5ul, representative_z.getNodeCount());
  127. EXPECT_TRUE(bddAllTrueOrAllFalse == representative_z);
  128. representative_xyz = bddAllTrueOrAllFalse.existsAbstractRepresentative({x.first, y.first, z.first});
  129. EXPECT_EQ(1ul, representative_xyz.getNonZeroCount());
  130. EXPECT_EQ(1ul, representative_xyz.getLeafCount());
  131. EXPECT_EQ(4ul, representative_xyz.getNodeCount());
  132. EXPECT_TRUE(bddX0Y0Z0 == representative_xyz);
  133. }
  134. TEST(SylvanDd, AddMinExistAbstractRepresentative) {
  135. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  136. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZero;
  137. ASSERT_NO_THROW(bddZero = manager->getBddZero());
  138. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddOne;
  139. ASSERT_NO_THROW(bddOne = manager->getBddOne());
  140. storm::dd::Add<storm::dd::DdType::Sylvan, double> addZero;
  141. ASSERT_NO_THROW(addZero = manager->template getAddZero<double>());
  142. storm::dd::Add<storm::dd::DdType::Sylvan, double> addOne;
  143. ASSERT_NO_THROW(addOne = manager->template getAddOne<double>());
  144. std::pair<storm::expressions::Variable, storm::expressions::Variable> x;
  145. std::pair<storm::expressions::Variable, storm::expressions::Variable> y;
  146. std::pair<storm::expressions::Variable, storm::expressions::Variable> z;
  147. ASSERT_NO_THROW(x = manager->addMetaVariable("x", 0, 1));
  148. ASSERT_NO_THROW(y = manager->addMetaVariable("y", 0, 1));
  149. ASSERT_NO_THROW(z = manager->addMetaVariable("z", 0, 1));
  150. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(x.first, 0);
  151. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(x.first, 1);
  152. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(y.first, 0);
  153. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(y.first, 1);
  154. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ0 = manager->getEncoding(z.first, 0);
  155. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ1 = manager->getEncoding(z.first, 1);
  156. storm::dd::Add<storm::dd::DdType::Sylvan, double> complexAdd =
  157. ((bddX1 && (bddY1 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.4))
  158. + ((bddX1 && (bddY1 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.7))
  159. + ((bddX1 && (bddY0 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.3))
  160. + ((bddX1 && (bddY0 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.3))
  161. + ((bddX0 && (bddY1 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.9))
  162. + ((bddX0 && (bddY1 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.5))
  163. + ((bddX0 && (bddY0 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(1.0))
  164. + ((bddX0 && (bddY0 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.0));
  165. // Abstract from FALSE
  166. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_false_x = addZero.minAbstractRepresentative({x.first});
  167. EXPECT_EQ(0ul, representative_false_x.getNonZeroCount());
  168. EXPECT_EQ(1ul, representative_false_x.getLeafCount());
  169. EXPECT_EQ(2ul, representative_false_x.getNodeCount());
  170. EXPECT_TRUE(representative_false_x == bddX0);
  171. // Abstract from TRUE
  172. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_x = addOne.minAbstractRepresentative({x.first});
  173. EXPECT_EQ(0ul, representative_true_x.getNonZeroCount());
  174. EXPECT_EQ(1ul, representative_true_x.getLeafCount());
  175. EXPECT_EQ(2ul, representative_true_x.getNodeCount());
  176. EXPECT_TRUE(representative_true_x == bddX0);
  177. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_xyz = addOne.minAbstractRepresentative({x.first, y.first, z.first});
  178. EXPECT_EQ(0ul, representative_true_xyz.getNonZeroCount());
  179. EXPECT_EQ(1ul, representative_true_xyz.getLeafCount());
  180. EXPECT_EQ(4ul, representative_true_xyz.getNodeCount());
  181. EXPECT_TRUE(representative_true_xyz == ((bddX0 && bddY0) && bddZ0));
  182. // Abstract x
  183. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_x = complexAdd.minAbstractRepresentative({x.first});
  184. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_x = (
  185. ((bddX0 && (bddY0 && bddZ0)))
  186. || ((bddX1 && (bddY0 && bddZ1)))
  187. || ((bddX0 && (bddY1 && bddZ0)))
  188. || ((bddX1 && (bddY1 && bddZ1)))
  189. );
  190. EXPECT_EQ(4ul, representative_complex_x.getNonZeroCount());
  191. EXPECT_EQ(1ul, representative_complex_x.getLeafCount());
  192. EXPECT_EQ(3ul, representative_complex_x.getNodeCount());
  193. EXPECT_TRUE(representative_complex_x == comparison_complex_x);
  194. // Abstract y
  195. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_y = complexAdd.minAbstractRepresentative({y.first});
  196. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_y = (
  197. ((bddX0 && (bddY0 && bddZ0)))
  198. || ((bddX0 && (bddY1 && bddZ1)))
  199. || ((bddX1 && (bddY0 && bddZ0)))
  200. || ((bddX1 && (bddY0 && bddZ1)))
  201. );
  202. EXPECT_EQ(4ul, representative_complex_y.getNonZeroCount());
  203. EXPECT_EQ(1ul, representative_complex_y.getLeafCount());
  204. EXPECT_EQ(5ul, representative_complex_y.getNodeCount());
  205. EXPECT_TRUE(representative_complex_y == comparison_complex_y);
  206. // Abstract z
  207. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_z = complexAdd.minAbstractRepresentative({z.first});
  208. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_z = (
  209. ((bddX0 && (bddY0 && bddZ0)))
  210. || ((bddX0 && (bddY1 && bddZ0)))
  211. || ((bddX1 && (bddY0 && bddZ0)))
  212. || ((bddX1 && (bddY1 && bddZ1)))
  213. );
  214. EXPECT_EQ(4ul, representative_complex_z.getNonZeroCount());
  215. EXPECT_EQ(1ul, representative_complex_z.getLeafCount());
  216. EXPECT_EQ(4ul, representative_complex_z.getNodeCount());
  217. EXPECT_TRUE(representative_complex_z == comparison_complex_z);
  218. // Abstract x, y, z
  219. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_xyz = complexAdd.minAbstractRepresentative({x.first, y.first, z.first});
  220. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_xyz = (bddX0 && (bddY0 && bddZ0));
  221. EXPECT_EQ(1ul, representative_complex_xyz.getNonZeroCount());
  222. EXPECT_EQ(1ul, representative_complex_xyz.getLeafCount());
  223. EXPECT_EQ(4ul, representative_complex_xyz.getNodeCount());
  224. EXPECT_TRUE(representative_complex_xyz == comparison_complex_xyz);
  225. }
  226. TEST(SylvanDd, AddMaxExistAbstractRepresentative) {
  227. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  228. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZero;
  229. ASSERT_NO_THROW(bddZero = manager->getBddZero());
  230. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddOne;
  231. ASSERT_NO_THROW(bddOne = manager->getBddOne());
  232. storm::dd::Add<storm::dd::DdType::Sylvan, double> addZero;
  233. ASSERT_NO_THROW(addZero = manager->template getAddZero<double>());
  234. storm::dd::Add<storm::dd::DdType::Sylvan, double> addOne;
  235. ASSERT_NO_THROW(addOne = manager->template getAddOne<double>());
  236. std::pair<storm::expressions::Variable, storm::expressions::Variable> x;
  237. std::pair<storm::expressions::Variable, storm::expressions::Variable> y;
  238. std::pair<storm::expressions::Variable, storm::expressions::Variable> z;
  239. ASSERT_NO_THROW(x = manager->addMetaVariable("x", 0, 1));
  240. ASSERT_NO_THROW(y = manager->addMetaVariable("y", 0, 1));
  241. ASSERT_NO_THROW(z = manager->addMetaVariable("z", 0, 1));
  242. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(x.first, 0);
  243. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(x.first, 1);
  244. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(y.first, 0);
  245. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(y.first, 1);
  246. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ0 = manager->getEncoding(z.first, 0);
  247. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ1 = manager->getEncoding(z.first, 1);
  248. storm::dd::Add<storm::dd::DdType::Sylvan, double> complexAdd =
  249. ((bddX1 && (bddY1 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.4))
  250. + ((bddX1 && (bddY1 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.7))
  251. + ((bddX1 && (bddY0 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.3))
  252. + ((bddX1 && (bddY0 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.3))
  253. + ((bddX0 && (bddY1 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(0.9))
  254. + ((bddX0 && (bddY1 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.5))
  255. + ((bddX0 && (bddY0 && bddZ1)).template toAdd<double>() * manager->template getConstant<double>(1.0))
  256. + ((bddX0 && (bddY0 && bddZ0)).template toAdd<double>() * manager->template getConstant<double>(0.0));
  257. // Abstract from FALSE
  258. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_false_x = addZero.maxAbstractRepresentative({x.first});
  259. EXPECT_EQ(0ul, representative_false_x.getNonZeroCount());
  260. EXPECT_EQ(1ul, representative_false_x.getLeafCount());
  261. EXPECT_EQ(2ul, representative_false_x.getNodeCount());
  262. EXPECT_TRUE(representative_false_x == bddX0);
  263. // Abstract from TRUE
  264. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_x = addOne.maxAbstractRepresentative({x.first});
  265. EXPECT_EQ(0ul, representative_true_x.getNonZeroCount());
  266. EXPECT_EQ(1ul, representative_true_x.getLeafCount());
  267. EXPECT_EQ(2ul, representative_true_x.getNodeCount());
  268. EXPECT_TRUE(representative_true_x == bddX0);
  269. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_true_xyz = addOne.maxAbstractRepresentative({x.first, y.first, z.first});
  270. EXPECT_EQ(0ul, representative_true_xyz.getNonZeroCount());
  271. EXPECT_EQ(1ul, representative_true_xyz.getLeafCount());
  272. EXPECT_EQ(4ul, representative_true_xyz.getNodeCount());
  273. EXPECT_TRUE(representative_true_xyz == ((bddX0 && bddY0) && bddZ0));
  274. // Abstract x
  275. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_x = complexAdd.maxAbstractRepresentative({x.first});
  276. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_x = (
  277. ((bddX1 && (bddY0 && bddZ0)))
  278. || ((bddX0 && (bddY0 && bddZ1)))
  279. || ((bddX1 && (bddY1 && bddZ0)))
  280. || ((bddX0 && (bddY1 && bddZ1)))
  281. );
  282. EXPECT_EQ(4ul, representative_complex_x.getNonZeroCount());
  283. EXPECT_EQ(1ul, representative_complex_x.getLeafCount());
  284. EXPECT_EQ(3ul, representative_complex_x.getNodeCount());
  285. EXPECT_TRUE(representative_complex_x == comparison_complex_x);
  286. // Abstract y
  287. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_y = complexAdd.maxAbstractRepresentative({y.first});
  288. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_y = (
  289. ((bddX0 && (bddY1 && bddZ0)))
  290. || ((bddX0 && (bddY0 && bddZ1)))
  291. || ((bddX1 && (bddY1 && bddZ0)))
  292. || ((bddX1 && (bddY1 && bddZ1)))
  293. );
  294. EXPECT_EQ(4ul, representative_complex_y.getNonZeroCount());
  295. EXPECT_EQ(1ul, representative_complex_y.getLeafCount());
  296. EXPECT_EQ(5ul, representative_complex_y.getNodeCount());
  297. EXPECT_TRUE(representative_complex_y == comparison_complex_y);
  298. // Abstract z
  299. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_z = complexAdd.maxAbstractRepresentative({z.first});
  300. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_z = (
  301. ((bddX0 && (bddY0 && bddZ1)))
  302. || ((bddX0 && (bddY1 && bddZ1)))
  303. || ((bddX1 && (bddY0 && bddZ0)))
  304. || ((bddX1 && (bddY1 && bddZ0)))
  305. );
  306. EXPECT_EQ(4ul, representative_complex_z.getNonZeroCount());
  307. EXPECT_EQ(1ul, representative_complex_z.getLeafCount());
  308. EXPECT_EQ(3ul, representative_complex_z.getNodeCount());
  309. EXPECT_TRUE(representative_complex_z == comparison_complex_z);
  310. // Abstract x, y, z
  311. storm::dd::Bdd<storm::dd::DdType::Sylvan> representative_complex_xyz = complexAdd.maxAbstractRepresentative({x.first, y.first, z.first});
  312. storm::dd::Bdd<storm::dd::DdType::Sylvan> comparison_complex_xyz = (bddX0 && (bddY0 && bddZ1));
  313. EXPECT_EQ(1ul, representative_complex_xyz.getNonZeroCount());
  314. EXPECT_EQ(1ul, representative_complex_xyz.getLeafCount());
  315. EXPECT_EQ(4ul, representative_complex_xyz.getNodeCount());
  316. EXPECT_TRUE(representative_complex_xyz == comparison_complex_xyz);
  317. }
  318. TEST(SylvanDd, AddGetMetaVariableTest) {
  319. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  320. ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
  321. EXPECT_EQ(2ul, manager->getNumberOfMetaVariables());
  322. ASSERT_THROW(manager->addMetaVariable("x", 0, 3), storm::exceptions::InvalidArgumentException);
  323. ASSERT_NO_THROW(manager->addMetaVariable("y", 0, 3));
  324. EXPECT_EQ(4ul, manager->getNumberOfMetaVariables());
  325. EXPECT_TRUE(manager->hasMetaVariable("x'"));
  326. EXPECT_TRUE(manager->hasMetaVariable("y'"));
  327. std::set<std::string> metaVariableSet = {"x", "x'", "y", "y'"};
  328. EXPECT_EQ(metaVariableSet, manager->getAllMetaVariableNames());
  329. }
  330. TEST(SylvanDd, EncodingTest) {
  331. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  332. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  333. storm::dd::Bdd<storm::dd::DdType::Sylvan> encoding;
  334. ASSERT_THROW(encoding = manager->getEncoding(x.first, 0), storm::exceptions::InvalidArgumentException);
  335. ASSERT_THROW(encoding = manager->getEncoding(x.first, 10), storm::exceptions::InvalidArgumentException);
  336. ASSERT_NO_THROW(encoding = manager->getEncoding(x.first, 4));
  337. EXPECT_EQ(1ul, encoding.getNonZeroCount());
  338. // As a BDD, this DD has one only leaf, because there does not exist a 0-leaf, and (consequently) one node less
  339. // than the MTBDD.
  340. EXPECT_EQ(5ul, encoding.getNodeCount());
  341. EXPECT_EQ(1ul, encoding.getLeafCount());
  342. storm::dd::Add<storm::dd::DdType::Sylvan, double> add;
  343. ASSERT_NO_THROW(add = encoding.template toAdd<double>());
  344. // As an MTBDD, the 0-leaf is there, so the count is actually 2 and the node count is 6.
  345. EXPECT_EQ(6ul, add.getNodeCount());
  346. EXPECT_EQ(2ul, add.getLeafCount());
  347. }
  348. #ifdef STORM_HAVE_CARL
  349. TEST(SylvanDd, RationalFunctionLeaveReplacementNonVariable) {
  350. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  351. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> zero;
  352. ASSERT_NO_THROW(zero = manager->template getAddZero<storm::RationalFunction>());
  353. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMap;
  354. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> zeroReplacementResult = zero.replaceLeaves(replacementMap);
  355. EXPECT_EQ(0ul, zeroReplacementResult.getNonZeroCount());
  356. EXPECT_EQ(1ul, zeroReplacementResult.getLeafCount());
  357. EXPECT_EQ(1ul, zeroReplacementResult.getNodeCount());
  358. EXPECT_TRUE(zeroReplacementResult == zero);
  359. }
  360. TEST(SylvanDd, RationalFunctionLeaveReplacementSimpleVariable) {
  361. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  362. // The cache that is used in case the underlying type needs a cache.
  363. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  364. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> function;
  365. carl::Variable x = carl::freshRealVariable("x");
  366. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  367. ASSERT_NO_THROW(function = manager->template getConstant<storm::RationalFunction>(variableX));
  368. std::pair<storm::expressions::Variable, storm::expressions::Variable> xExpr;
  369. ASSERT_NO_THROW(xExpr = manager->addMetaVariable("x", 0, 1));
  370. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMap;
  371. storm::RationalNumber rnOneThird = storm::RationalNumber(1) / storm::RationalNumber(3);
  372. storm::RationalNumber rnTwoThird = storm::RationalNumber(2) / storm::RationalNumber(3);
  373. replacementMap.insert(std::make_pair(x, std::make_pair(xExpr.first, std::make_pair(rnOneThird, rnTwoThird))));
  374. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> replacedAddSimpleX = function.replaceLeaves(replacementMap);
  375. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(xExpr.first, 0);
  376. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(xExpr.first, 1);
  377. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> complexAdd =
  378. (bddX0.template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnTwoThird)))
  379. + (bddX1.template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnOneThird)));
  380. EXPECT_EQ(2ul, replacedAddSimpleX.getNonZeroCount());
  381. EXPECT_EQ(2ul, replacedAddSimpleX.getLeafCount());
  382. EXPECT_EQ(3ul, replacedAddSimpleX.getNodeCount());
  383. EXPECT_TRUE(replacedAddSimpleX == complexAdd);
  384. }
  385. TEST(SylvanDd, RationalFunctionLeaveReplacementTwoVariables) {
  386. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  387. // The cache that is used in case the underlying type needs a cache.
  388. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  389. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> function;
  390. carl::Variable x = carl::freshRealVariable("x");
  391. carl::Variable y = carl::freshRealVariable("y");
  392. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  393. storm::RationalFunction variableY = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(y), cache));
  394. ASSERT_NO_THROW(function = manager->template getConstant<storm::RationalFunction>(variableX * variableY));
  395. std::pair<storm::expressions::Variable, storm::expressions::Variable> xExpr;
  396. std::pair<storm::expressions::Variable, storm::expressions::Variable> yExpr;
  397. ASSERT_NO_THROW(xExpr = manager->addMetaVariable("x", 0, 1));
  398. ASSERT_NO_THROW(yExpr = manager->addMetaVariable("y", 0, 1));
  399. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMap;
  400. storm::RationalNumber rnOneThird = storm::RationalNumber(1) / storm::RationalNumber(3);
  401. storm::RationalNumber rnTwoThird = storm::RationalNumber(2) / storm::RationalNumber(3);
  402. storm::RationalNumber rnOne = storm::RationalNumber(1);
  403. storm::RationalNumber rnTen = storm::RationalNumber(10);
  404. replacementMap.insert(std::make_pair(x, std::make_pair(xExpr.first, std::make_pair(rnOneThird, rnTwoThird))));
  405. replacementMap.insert(std::make_pair(y, std::make_pair(yExpr.first, std::make_pair(rnOne, rnTen))));
  406. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> replacedAdd = function.replaceLeaves(replacementMap);
  407. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(xExpr.first, 0);
  408. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(xExpr.first, 1);
  409. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(yExpr.first, 0);
  410. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(yExpr.first, 1);
  411. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> complexAdd =
  412. ((bddX0 && bddY0).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnTwoThird * rnTen)))
  413. + ((bddX0 && bddY1).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnTwoThird)))
  414. + ((bddX1 && bddY0).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnOneThird * rnTen)))
  415. + ((bddX1 && bddY1).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(rnOneThird)));
  416. EXPECT_EQ(4ul, replacedAdd.getNonZeroCount());
  417. EXPECT_EQ(4ul, replacedAdd.getLeafCount());
  418. EXPECT_EQ(7ul, replacedAdd.getNodeCount());
  419. EXPECT_TRUE(replacedAdd == complexAdd);
  420. }
  421. TEST(SylvanDd, RationalFunctionBullshitTest) {
  422. // The cache that is used in case the underlying type needs a cache.
  423. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  424. carl::Variable x = carl::freshRealVariable("x");
  425. carl::Variable y = carl::freshRealVariable("y");
  426. carl::Variable z = carl::freshRealVariable("z");
  427. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  428. storm::RationalFunction variableY = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(y), cache));
  429. storm::RationalFunction variableZ = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(z), cache));
  430. storm::RationalFunction constantOne(1);
  431. storm::RationalFunction constantTwo(2);
  432. storm::RationalFunction constantOneDivTwo(constantOne / constantTwo);
  433. storm::RationalFunction tmpFunctionA(constantOneDivTwo);
  434. tmpFunctionA *= variableZ;
  435. tmpFunctionA /= variableY;
  436. storm::RationalFunction tmpFunctionB(variableX);
  437. tmpFunctionB *= variableY;
  438. //storm::RationalFunction rationalFunction(two * x + x*y + constantOneDivTwo * z / y);
  439. storm::RationalFunction rationalFunction(constantTwo);
  440. rationalFunction *= variableX;
  441. rationalFunction += tmpFunctionB;
  442. rationalFunction += tmpFunctionA;
  443. std::map<storm::RationalFunctionVariable, storm::RationalNumber> replacement = {{x, storm::RationalNumber(2)}};
  444. storm::RationalFunction subX = rationalFunction.substitute(replacement);
  445. ASSERT_EQ(subX, storm::RationalFunction(4) + storm::RationalFunction(2) * variableY + tmpFunctionA);
  446. }
  447. TEST(SylvanDd, RationalFunctionLeaveReplacementComplexFunction) {
  448. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  449. // The cache that is used in case the underlying type needs a cache.
  450. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  451. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> function;
  452. carl::Variable x = carl::freshRealVariable("x");
  453. carl::Variable y = carl::freshRealVariable("y");
  454. carl::Variable z = carl::freshRealVariable("z");
  455. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  456. storm::RationalFunction variableY = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(y), cache));
  457. storm::RationalFunction variableZ = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(z), cache));
  458. storm::RationalFunction constantOne(1);
  459. storm::RationalFunction constantTwo(2);
  460. storm::RationalFunction constantOneDivTwo(constantOne / constantTwo);
  461. storm::RationalFunction tmpFunctionA(constantOneDivTwo);
  462. tmpFunctionA *= variableZ;
  463. tmpFunctionA /= variableY;
  464. storm::RationalFunction tmpFunctionB(variableX);
  465. tmpFunctionB *= variableY;
  466. //storm::RationalFunction rationalFunction(two * x + x*y + constantOneDivTwo * z / y);
  467. storm::RationalFunction rationalFunction(constantTwo);
  468. rationalFunction *= variableX;
  469. rationalFunction += tmpFunctionB;
  470. rationalFunction += tmpFunctionA;
  471. ASSERT_NO_THROW(function = manager->template getConstant<storm::RationalFunction>(rationalFunction));
  472. std::pair<storm::expressions::Variable, storm::expressions::Variable> xExpr;
  473. std::pair<storm::expressions::Variable, storm::expressions::Variable> yExpr;
  474. std::pair<storm::expressions::Variable, storm::expressions::Variable> zExpr;
  475. ASSERT_NO_THROW(xExpr = manager->addMetaVariable("x", 0, 1));
  476. ASSERT_NO_THROW(yExpr = manager->addMetaVariable("y", 0, 1));
  477. ASSERT_NO_THROW(zExpr = manager->addMetaVariable("z", 0, 1));
  478. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMap;
  479. storm::RationalNumber rnTwo(2);
  480. storm::RationalNumber rnThree(3);
  481. storm::RationalNumber rnFive(5);
  482. storm::RationalNumber rnSeven(7);
  483. storm::RationalNumber rnEleven(11);
  484. storm::RationalNumber rnThirteen(13);
  485. replacementMap.insert(std::make_pair(x, std::make_pair(xExpr.first, std::make_pair(rnTwo, rnSeven))));
  486. replacementMap.insert(std::make_pair(y, std::make_pair(yExpr.first, std::make_pair(rnThree, rnEleven))));
  487. replacementMap.insert(std::make_pair(z, std::make_pair(zExpr.first, std::make_pair(rnFive, rnThirteen))));
  488. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> replacedAdd = function.replaceLeaves(replacementMap);
  489. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(xExpr.first, 0);
  490. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(xExpr.first, 1);
  491. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(yExpr.first, 0);
  492. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(yExpr.first, 1);
  493. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ0 = manager->getEncoding(zExpr.first, 0);
  494. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ1 = manager->getEncoding(zExpr.first, 1);
  495. auto f = [&](bool x, bool y, bool z) {
  496. storm::RationalNumber result(2);
  497. if (x) {
  498. result *= rnSeven;
  499. } else {
  500. result *= rnTwo;
  501. }
  502. storm::RationalNumber partTwo(1);
  503. if (x) {
  504. partTwo *= rnSeven;
  505. } else {
  506. partTwo *= rnTwo;
  507. }
  508. if (y) {
  509. partTwo *= rnEleven;
  510. } else {
  511. partTwo *= rnThree;
  512. }
  513. storm::RationalNumber partThree(1);
  514. if (z) {
  515. partThree *= rnThirteen;
  516. } else {
  517. partThree *= rnFive;
  518. }
  519. if (y) {
  520. partThree /= storm::RationalNumber(2) * rnEleven;
  521. } else {
  522. partThree /= storm::RationalNumber(2) * rnThree;
  523. }
  524. return result + partTwo + partThree;
  525. };
  526. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> complexAdd =
  527. ((bddX0 && (bddY0 && bddZ0)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(false, false, false))))
  528. + ((bddX0 && (bddY0 && bddZ1)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(false, false, true))))
  529. + ((bddX0 && (bddY1 && bddZ0)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(false, true, false))))
  530. + ((bddX0 && (bddY1 && bddZ1)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(false, true, true))))
  531. + ((bddX1 && (bddY0 && bddZ0)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(true, false, false))))
  532. + ((bddX1 && (bddY0 && bddZ1)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(true, false, true))))
  533. + ((bddX1 && (bddY1 && bddZ0)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(true, true, false))))
  534. + ((bddX1 && (bddY1 && bddZ1)).template toAdd<storm::RationalFunction>() * manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(f(true, true, true))));
  535. EXPECT_EQ(4ul, replacedAdd.getNonZeroCount());
  536. EXPECT_EQ(4ul, replacedAdd.getLeafCount());
  537. EXPECT_EQ(7ul, replacedAdd.getNodeCount());
  538. EXPECT_TRUE(replacedAdd == complexAdd);
  539. replacedAdd.exportToDot("sylvan_replacedAddC.dot");
  540. complexAdd.exportToDot("sylvan_complexAddC.dot");
  541. }
  542. TEST(SylvanDd, RationalFunctionLeaveReplacementComplexFunction2) {
  543. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  544. // The cache that is used in case the underlying type needs a cache.
  545. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  546. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> function;
  547. carl::Variable x = carl::freshRealVariable("x");
  548. carl::Variable y = carl::freshRealVariable("y");
  549. carl::Variable z = carl::freshRealVariable("z");
  550. storm::RationalFunction constantOne(1);
  551. storm::RationalFunction constantTwo(2);
  552. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  553. storm::RationalFunction variableY = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(y), cache));
  554. storm::RationalFunction variableZ = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(z), cache));
  555. storm::RationalFunction constantOneDivTwo(constantOne / constantTwo);
  556. storm::RationalFunction tmpFunctionA(constantOneDivTwo);
  557. tmpFunctionA *= variableZ;
  558. tmpFunctionA /= variableY;
  559. storm::RationalFunction tmpFunctionB(variableX);
  560. tmpFunctionB *= variableY;
  561. //storm::RationalFunction rationalFunction(two * x + x*y + constantOneDivTwo * z / y);
  562. storm::RationalFunction rationalFunction(constantTwo);
  563. rationalFunction *= variableX;
  564. rationalFunction += tmpFunctionB;
  565. rationalFunction += tmpFunctionA;
  566. ASSERT_NO_THROW(function = manager->template getConstant<storm::RationalFunction>(rationalFunction));
  567. EXPECT_EQ(0ul, function.getNonZeroCount());
  568. EXPECT_EQ(1ul, function.getLeafCount());
  569. EXPECT_EQ(1ul, function.getNodeCount());
  570. std::pair<storm::expressions::Variable, storm::expressions::Variable> xExpr;
  571. std::pair<storm::expressions::Variable, storm::expressions::Variable> yExpr;
  572. std::pair<storm::expressions::Variable, storm::expressions::Variable> zExpr;
  573. ASSERT_NO_THROW(xExpr = manager->addMetaVariable("x", 0, 1));
  574. ASSERT_NO_THROW(yExpr = manager->addMetaVariable("y", 0, 1));
  575. ASSERT_NO_THROW(zExpr = manager->addMetaVariable("z", 0, 1));
  576. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX0 = manager->getEncoding(xExpr.first, 0);
  577. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddX1 = manager->getEncoding(xExpr.first, 1);
  578. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY0 = manager->getEncoding(yExpr.first, 0);
  579. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddY1 = manager->getEncoding(yExpr.first, 1);
  580. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ0 = manager->getEncoding(zExpr.first, 0);
  581. storm::dd::Bdd<storm::dd::DdType::Sylvan> bddZ1 = manager->getEncoding(zExpr.first, 1);
  582. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> functionSimpleX;
  583. ASSERT_NO_THROW(functionSimpleX = manager->template getConstant<storm::RationalFunction>(storm::RationalFunction(variableX)));
  584. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMapSimpleX;
  585. storm::RationalNumber rnOneThird = storm::RationalNumber(1) / storm::RationalNumber(3);
  586. storm::RationalNumber rnTwoThird = storm::RationalNumber(2) / storm::RationalNumber(3);
  587. replacementMapSimpleX.insert(std::make_pair(x, std::make_pair(xExpr.first, std::make_pair(rnOneThird, rnTwoThird))));
  588. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> replacedAddSimpleX = functionSimpleX.replaceLeaves(replacementMapSimpleX);
  589. replacedAddSimpleX.exportToDot("sylvan_replacementMapSimpleX.dot");
  590. std::map<storm::RationalFunctionVariable, std::pair<storm::expressions::Variable, std::pair<storm::RationalNumber, storm::RationalNumber>>> replacementMap;
  591. storm::RationalNumber rnMinusOne(-1);
  592. storm::RationalNumber rnOne(1);
  593. storm::RationalNumber rnPointOne = storm::RationalNumber(1) / storm::RationalNumber(10);
  594. storm::RationalNumber rnPointSixSix = storm::RationalNumber(2) / storm::RationalNumber(3);
  595. storm::RationalNumber rnPointFive = storm::RationalNumber(1) / storm::RationalNumber(2);
  596. replacementMap.insert(std::make_pair(x, std::make_pair(xExpr.first, std::make_pair(rnMinusOne, rnOne))));
  597. replacementMap.insert(std::make_pair(y, std::make_pair(yExpr.first, std::make_pair(rnPointOne, rnPointSixSix))));
  598. replacementMap.insert(std::make_pair(z, std::make_pair(zExpr.first, std::make_pair(rnPointFive, rnOne))));
  599. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> replacedAdd = function.replaceLeaves(replacementMap);
  600. replacedAdd.exportToDot("sylvan_replaceLeave.dot");
  601. }
  602. TEST(SylvanDd, RationalFunctionConstants) {
  603. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  604. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> zero;
  605. ASSERT_NO_THROW(zero = manager->template getAddZero<storm::RationalFunction>());
  606. EXPECT_EQ(0ul, zero.getNonZeroCount());
  607. EXPECT_EQ(1ul, zero.getLeafCount());
  608. EXPECT_EQ(1ul, zero.getNodeCount());
  609. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> one;
  610. ASSERT_NO_THROW(one = manager->template getAddOne<storm::RationalFunction>());
  611. EXPECT_EQ(0ul, one.getNonZeroCount());
  612. EXPECT_EQ(1ul, one.getLeafCount());
  613. EXPECT_EQ(1ul, one.getNodeCount());
  614. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> two;
  615. storm::RationalFunction constantTwo(2);
  616. ASSERT_NO_THROW(two = manager->template getConstant<storm::RationalFunction>(constantTwo));
  617. EXPECT_EQ(0ul, two.getNonZeroCount());
  618. EXPECT_EQ(1ul, two.getLeafCount());
  619. EXPECT_EQ(1ul, two.getNodeCount());
  620. // The cache that is used in case the underlying type needs a cache.
  621. std::shared_ptr<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>> cache = std::make_shared<carl::Cache<carl::PolynomialFactorizationPair<storm::RawPolynomial>>>();
  622. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> function;
  623. carl::Variable x = carl::freshRealVariable("x");
  624. carl::Variable y = carl::freshRealVariable("y");
  625. carl::Variable z = carl::freshRealVariable("z");
  626. storm::RationalFunction constantOne(1);
  627. storm::RationalFunction variableX = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(x), cache));
  628. storm::RationalFunction variableY = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(y), cache));
  629. storm::RationalFunction variableZ = storm::RationalFunction(typename storm::RationalFunction::PolyType(typename storm::RationalFunction::PolyType::PolyType(z), cache));
  630. storm::RationalFunction constantOneDivTwo(constantOne / constantTwo);
  631. storm::RationalFunction tmpFunctionA(constantOneDivTwo);
  632. tmpFunctionA *= variableZ;
  633. tmpFunctionA /= variableY;
  634. storm::RationalFunction tmpFunctionB(variableX);
  635. tmpFunctionB *= variableY;
  636. //storm::RationalFunction rationalFunction(two * x + x*y + constantOneDivTwo * z / y);
  637. storm::RationalFunction rationalFunction(constantTwo);
  638. rationalFunction *= variableX;
  639. rationalFunction += tmpFunctionB;
  640. rationalFunction += tmpFunctionA;
  641. ASSERT_NO_THROW(function = manager->template getConstant<storm::RationalFunction>(rationalFunction));
  642. EXPECT_EQ(0ul, function.getNonZeroCount());
  643. EXPECT_EQ(1ul, function.getLeafCount());
  644. EXPECT_EQ(1ul, function.getNodeCount());
  645. }
  646. TEST(SylvanDd, RationalFunctionEncodingTest) {
  647. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  648. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  649. storm::dd::Bdd<storm::dd::DdType::Sylvan> encoding;
  650. ASSERT_THROW(encoding = manager->getEncoding(x.first, 0), storm::exceptions::InvalidArgumentException);
  651. ASSERT_THROW(encoding = manager->getEncoding(x.first, 10), storm::exceptions::InvalidArgumentException);
  652. ASSERT_NO_THROW(encoding = manager->getEncoding(x.first, 4));
  653. EXPECT_EQ(1ul, encoding.getNonZeroCount());
  654. // As a BDD, this DD has one only leaf, because there does not exist a 0-leaf, and (consequently) one node less
  655. // than the MTBDD.
  656. EXPECT_EQ(5ul, encoding.getNodeCount());
  657. EXPECT_EQ(1ul, encoding.getLeafCount());
  658. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> add;
  659. ASSERT_NO_THROW(add = encoding.template toAdd<storm::RationalFunction>());
  660. // As an MTBDD, the 0-leaf is there, so the count is actually 2 and the node count is 6.
  661. EXPECT_EQ(6ul, add.getNodeCount());
  662. EXPECT_EQ(2ul, add.getLeafCount());
  663. }
  664. TEST(SylvanDd, RationalFunctionIdentityTest) {
  665. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  666. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  667. storm::dd::Add<storm::dd::DdType::Sylvan, storm::RationalFunction> identity;
  668. ASSERT_NO_THROW(identity = manager->getIdentity<storm::RationalFunction>(x.first));
  669. EXPECT_EQ(9ul, identity.getNonZeroCount());
  670. EXPECT_EQ(10ul, identity.getLeafCount());
  671. EXPECT_EQ(21ul, identity.getNodeCount());
  672. }
  673. #endif
  674. TEST(SylvanDd, RangeTest) {
  675. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  676. std::pair<storm::expressions::Variable, storm::expressions::Variable> x;
  677. ASSERT_NO_THROW(x = manager->addMetaVariable("x", 1, 9));
  678. storm::dd::Bdd<storm::dd::DdType::Sylvan> range;
  679. ASSERT_NO_THROW(range = manager->getRange(x.first));
  680. EXPECT_EQ(9ul, range.getNonZeroCount());
  681. EXPECT_EQ(1ul, range.getLeafCount());
  682. EXPECT_EQ(5ul, range.getNodeCount());
  683. }
  684. TEST(SylvanDd, DoubleIdentityTest) {
  685. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  686. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  687. storm::dd::Add<storm::dd::DdType::Sylvan, double> identity;
  688. ASSERT_NO_THROW(identity = manager->getIdentity<double>(x.first));
  689. EXPECT_EQ(9ul, identity.getNonZeroCount());
  690. EXPECT_EQ(10ul, identity.getLeafCount());
  691. EXPECT_EQ(21ul, identity.getNodeCount());
  692. }
  693. TEST(SylvanDd, UintIdentityTest) {
  694. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  695. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  696. storm::dd::Add<storm::dd::DdType::Sylvan, uint_fast64_t> identity;
  697. ASSERT_NO_THROW(identity = manager->getIdentity<uint_fast64_t>(x.first));
  698. EXPECT_EQ(9ul, identity.getNonZeroCount());
  699. EXPECT_EQ(10ul, identity.getLeafCount());
  700. EXPECT_EQ(21ul, identity.getNodeCount());
  701. }
  702. TEST(SylvanDd, OperatorTest) {
  703. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  704. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  705. EXPECT_TRUE(manager->template getAddZero<double>() == manager->template getAddZero<double>());
  706. EXPECT_FALSE(manager->template getAddZero<double>() == manager->template getAddOne<double>());
  707. EXPECT_FALSE(manager->template getAddZero<double>() != manager->template getAddZero<double>());
  708. EXPECT_TRUE(manager->template getAddZero<double>() != manager->template getAddOne<double>());
  709. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd1 = manager->template getAddOne<double>();
  710. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd2 = manager->template getAddOne<double>();
  711. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd3 = dd1 + dd2;
  712. storm::dd::Bdd<storm::dd::DdType::Sylvan> bdd;
  713. EXPECT_TRUE(dd3 == manager->template getConstant<double>(2));
  714. dd3 += manager->template getAddZero<double>();
  715. EXPECT_TRUE(dd3 == manager->template getConstant<double>(2));
  716. dd3 = dd1 * manager->template getConstant<double>(3);
  717. EXPECT_TRUE(dd3 == manager->template getConstant<double>(3));
  718. dd3 *= manager->template getConstant<double>(2);
  719. EXPECT_TRUE(dd3 == manager->template getConstant<double>(6));
  720. dd3 = dd1 - dd2;
  721. EXPECT_TRUE(dd3.isZero());
  722. dd3 -= manager->template getConstant<double>(-2);
  723. EXPECT_TRUE(dd3 == manager->template getConstant<double>(2));
  724. dd3 /= manager->template getConstant<double>(2);
  725. EXPECT_TRUE(dd3.isOne());
  726. bdd = !dd3.toBdd();
  727. EXPECT_TRUE(bdd.isZero());
  728. bdd = !bdd;
  729. EXPECT_TRUE(bdd.isOne());
  730. bdd = dd1.toBdd() || dd2.toBdd();
  731. EXPECT_TRUE(bdd.isOne());
  732. dd1 = manager->template getIdentity<double>(x.first);
  733. dd2 = manager->template getConstant<double>(5);
  734. bdd = dd1.equals(dd2);
  735. EXPECT_EQ(1ul, bdd.getNonZeroCount());
  736. storm::dd::Bdd<storm::dd::DdType::Sylvan> bdd2 = dd1.notEquals(dd2);
  737. EXPECT_TRUE(bdd2 == !bdd);
  738. bdd = dd1.less(dd2);
  739. EXPECT_EQ(11ul, bdd.getNonZeroCount());
  740. bdd = dd1.lessOrEqual(dd2);
  741. EXPECT_EQ(12ul, bdd.getNonZeroCount());
  742. bdd = dd1.greater(dd2);
  743. EXPECT_EQ(4ul, bdd.getNonZeroCount());
  744. bdd = dd1.greaterOrEqual(dd2);
  745. EXPECT_EQ(5ul, bdd.getNonZeroCount());
  746. dd3 = manager->getEncoding(x.first, 2).ite(dd2, dd1);
  747. bdd = dd3.less(dd2);
  748. EXPECT_EQ(10ul, bdd.getNonZeroCount());
  749. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd4 = dd3.minimum(dd1);
  750. dd4 *= manager->getEncoding(x.first, 2).template toAdd<double>();
  751. dd4 = dd4.sumAbstract({x.first});
  752. EXPECT_EQ(2, dd4.getValue());
  753. dd4 = dd3.maximum(dd1);
  754. dd4 *= manager->getEncoding(x.first, 2).template toAdd<double>();
  755. dd4 = dd4.sumAbstract({x.first});
  756. EXPECT_EQ(5, dd4.getValue());
  757. dd1 = manager->template getConstant<double>(0.01);
  758. dd2 = manager->template getConstant<double>(0.01 + 1e-6);
  759. EXPECT_TRUE(dd1.equalModuloPrecision(dd2, 1e-6, false));
  760. EXPECT_FALSE(dd1.equalModuloPrecision(dd2, 1e-6));
  761. }
  762. TEST(SylvanDd, AbstractionTest) {
  763. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  764. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  765. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd1;
  766. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd2;
  767. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd3;
  768. storm::dd::Bdd<storm::dd::DdType::Sylvan> bdd;
  769. dd1 = manager->template getIdentity<double>(x.first);
  770. dd2 = manager->template getConstant<double>(5);
  771. bdd = dd1.equals(dd2);
  772. EXPECT_EQ(1ul, bdd.getNonZeroCount());
  773. ASSERT_THROW(bdd = bdd.existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
  774. ASSERT_NO_THROW(bdd = bdd.existsAbstract({x.first}));
  775. EXPECT_EQ(0ul, bdd.getNonZeroCount());
  776. EXPECT_EQ(1, bdd.template toAdd<double>().getMax());
  777. dd3 = dd1.equals(dd2).template toAdd<double>();
  778. dd3 *= manager->template getConstant<double>(3);
  779. EXPECT_EQ(1ul, dd3.getNonZeroCount());
  780. ASSERT_THROW(bdd = dd3.toBdd().existsAbstract({x.second}), storm::exceptions::InvalidArgumentException);
  781. ASSERT_NO_THROW(bdd = dd3.toBdd().existsAbstract({x.first}));
  782. EXPECT_TRUE(bdd.isOne());
  783. dd3 = dd1.equals(dd2).template toAdd<double>();
  784. dd3 *= manager->template getConstant<double>(3);
  785. ASSERT_THROW(dd3 = dd3.sumAbstract({x.second}), storm::exceptions::InvalidArgumentException);
  786. ASSERT_NO_THROW(dd3 = dd3.sumAbstract({x.first}));
  787. EXPECT_EQ(0ul, dd3.getNonZeroCount());
  788. EXPECT_EQ(3, dd3.getMax());
  789. dd3 = dd1.equals(dd2).template toAdd<double>();
  790. dd3 *= manager->template getConstant<double>(3);
  791. ASSERT_THROW(dd3 = dd3.minAbstract({x.second}), storm::exceptions::InvalidArgumentException);
  792. ASSERT_NO_THROW(dd3 = dd3.minAbstract({x.first}));
  793. EXPECT_EQ(0ul, dd3.getNonZeroCount());
  794. EXPECT_EQ(0, dd3.getMax());
  795. dd3 = dd1.equals(dd2).template toAdd<double>();
  796. dd3 *= manager->template getConstant<double>(3);
  797. ASSERT_THROW(dd3 = dd3.maxAbstract({x.second}), storm::exceptions::InvalidArgumentException);
  798. ASSERT_NO_THROW(dd3 = dd3.maxAbstract({x.first}));
  799. EXPECT_EQ(0ul, dd3.getNonZeroCount());
  800. EXPECT_EQ(3, dd3.getMax());
  801. }
  802. TEST(SylvanDd, SwapTest) {
  803. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  804. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  805. std::pair<storm::expressions::Variable, storm::expressions::Variable> z = manager->addMetaVariable("z", 2, 8);
  806. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd1;
  807. dd1 = manager->template getIdentity<double>(x.first);
  808. ASSERT_THROW(dd1 = dd1.swapVariables({std::make_pair(x.first, z.first)}), storm::exceptions::InvalidArgumentException);
  809. ASSERT_NO_THROW(dd1 = dd1.swapVariables({std::make_pair(x.first, x.second)}));
  810. EXPECT_TRUE(dd1 == manager->template getIdentity<double>(x.second));
  811. }
  812. TEST(SylvanDd, MultiplyMatrixTest) {
  813. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  814. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  815. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd1 = manager->template getIdentity<double>(x.first).equals(manager->template getIdentity<double>(x.second)).template toAdd<double>();
  816. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd2 = manager->getRange(x.second).template toAdd<double>();
  817. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd3;
  818. dd1 *= manager->template getConstant<double>(2);
  819. ASSERT_NO_THROW(dd3 = dd1.multiplyMatrix(dd2, {x.second}));
  820. ASSERT_NO_THROW(dd3 = dd3.swapVariables({std::make_pair(x.first, x.second)}));
  821. EXPECT_TRUE(dd3 == dd2 * manager->template getConstant<double>(2));
  822. }
  823. TEST(SylvanDd, GetSetValueTest) {
  824. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  825. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  826. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd1 = manager->template getAddOne<double>();
  827. ASSERT_NO_THROW(dd1.setValue(x.first, 4, 2));
  828. EXPECT_EQ(2ul, dd1.getLeafCount());
  829. std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
  830. metaVariableToValueMap.emplace(x.first, 1);
  831. EXPECT_EQ(1, dd1.getValue(metaVariableToValueMap));
  832. metaVariableToValueMap.clear();
  833. metaVariableToValueMap.emplace(x.first, 4);
  834. EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap));
  835. }
  836. TEST(SylvanDd, AddIteratorTest) {
  837. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  838. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  839. std::pair<storm::expressions::Variable, storm::expressions::Variable> y = manager->addMetaVariable("y", 0, 3);
  840. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd;
  841. ASSERT_NO_THROW(dd = manager->getRange(x.first).template toAdd<double>());
  842. storm::dd::AddIterator<storm::dd::DdType::Sylvan, double> it, ite;
  843. ASSERT_NO_THROW(it = dd.begin());
  844. ASSERT_NO_THROW(ite = dd.end());
  845. std::pair<storm::expressions::SimpleValuation, double> valuationValuePair;
  846. uint_fast64_t numberOfValuations = 0;
  847. dd.exportToDot("dd.dot");
  848. while (it != ite) {
  849. ASSERT_NO_THROW(valuationValuePair = *it);
  850. ASSERT_NO_THROW(++it);
  851. ++numberOfValuations;
  852. }
  853. EXPECT_EQ(9ul, numberOfValuations);
  854. dd = manager->getRange(x.first).template toAdd<double>();
  855. dd = dd.notZero().ite(manager->template getAddOne<double>(), manager->template getAddOne<double>());
  856. ASSERT_NO_THROW(it = dd.begin());
  857. ASSERT_NO_THROW(ite = dd.end());
  858. numberOfValuations = 0;
  859. while (it != ite) {
  860. ASSERT_NO_THROW(valuationValuePair = *it);
  861. ASSERT_NO_THROW(++it);
  862. ++numberOfValuations;
  863. }
  864. EXPECT_EQ(16ul, numberOfValuations);
  865. ASSERT_NO_THROW(it = dd.begin(false));
  866. ASSERT_NO_THROW(ite = dd.end());
  867. numberOfValuations = 0;
  868. while (it != ite) {
  869. ASSERT_NO_THROW(valuationValuePair = *it);
  870. ASSERT_NO_THROW(++it);
  871. ++numberOfValuations;
  872. }
  873. EXPECT_EQ(1ul, numberOfValuations);
  874. }
  875. TEST(SylvanDd, AddOddTest) {
  876. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  877. std::pair<storm::expressions::Variable, storm::expressions::Variable> a = manager->addMetaVariable("a");
  878. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  879. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd = manager->template getIdentity<double>(x.first);
  880. storm::dd::Odd odd;
  881. ASSERT_NO_THROW(odd = dd.createOdd());
  882. EXPECT_EQ(9ul, odd.getTotalOffset());
  883. EXPECT_EQ(12ul, odd.getNodeCount());
  884. std::vector<double> ddAsVector;
  885. ASSERT_NO_THROW(ddAsVector = dd.toVector());
  886. EXPECT_EQ(9ul, ddAsVector.size());
  887. for (uint_fast64_t i = 0; i < ddAsVector.size(); ++i) {
  888. EXPECT_TRUE(i+1 == ddAsVector[i]);
  889. }
  890. // Create a non-trivial matrix.
  891. dd = manager->template getIdentity<double>(x.first).equals(manager->template getIdentity<double>(x.second)).template toAdd<double>() * manager->getRange(x.first).template toAdd<double>();
  892. dd += manager->getEncoding(x.first, 1).template toAdd<double>() * manager->getRange(x.second).template toAdd<double>() + manager->getEncoding(x.second, 1).template toAdd<double>() * manager->getRange(x.first).template toAdd<double>();
  893. // Create the ODDs.
  894. storm::dd::Odd rowOdd;
  895. ASSERT_NO_THROW(rowOdd = manager->getRange(x.first).template toAdd<double>().createOdd());
  896. storm::dd::Odd columnOdd;
  897. ASSERT_NO_THROW(columnOdd = manager->getRange(x.second).template toAdd<double>().createOdd());
  898. // Try to translate the matrix.
  899. storm::storage::SparseMatrix<double> matrix;
  900. ASSERT_NO_THROW(matrix = dd.toMatrix({x.first}, {x.second}, rowOdd, columnOdd));
  901. EXPECT_EQ(9ul, matrix.getRowCount());
  902. EXPECT_EQ(9ul, matrix.getColumnCount());
  903. EXPECT_EQ(25ul, matrix.getNonzeroEntryCount());
  904. dd = manager->getRange(x.first).template toAdd<double>() * manager->getRange(x.second).template toAdd<double>() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant<double>(1));
  905. ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd));
  906. EXPECT_EQ(18ul, matrix.getRowCount());
  907. EXPECT_EQ(9ul, matrix.getRowGroupCount());
  908. EXPECT_EQ(9ul, matrix.getColumnCount());
  909. EXPECT_EQ(106ul, matrix.getNonzeroEntryCount());
  910. }
  911. TEST(SylvanDd, BddOddTest) {
  912. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> manager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  913. std::pair<storm::expressions::Variable, storm::expressions::Variable> a = manager->addMetaVariable("a");
  914. std::pair<storm::expressions::Variable, storm::expressions::Variable> x = manager->addMetaVariable("x", 1, 9);
  915. storm::dd::Add<storm::dd::DdType::Sylvan, double> dd = manager->template getIdentity<double>(x.first);
  916. storm::dd::Bdd<storm::dd::DdType::Sylvan> bdd = dd.notZero();
  917. storm::dd::Odd odd;
  918. ASSERT_NO_THROW(odd = bdd.createOdd());
  919. EXPECT_EQ(9ul, odd.getTotalOffset());
  920. EXPECT_EQ(5ul, odd.getNodeCount());
  921. std::vector<double> ddAsVector;
  922. ASSERT_NO_THROW(ddAsVector = dd.toVector());
  923. EXPECT_EQ(9ul, ddAsVector.size());
  924. for (uint_fast64_t i = 0; i < ddAsVector.size(); ++i) {
  925. EXPECT_EQ(i+1, ddAsVector[i]);
  926. }
  927. storm::dd::Add<storm::dd::DdType::Sylvan, double> vectorAdd = storm::dd::Add<storm::dd::DdType::Sylvan, double>::fromVector(*manager, ddAsVector, odd, {x.first});
  928. // Create a non-trivial matrix.
  929. dd = manager->template getIdentity<double>(x.first).equals(manager->template getIdentity<double>(x.second)).template toAdd<double>() * manager->getRange(x.first).template toAdd<double>();
  930. dd += manager->getEncoding(x.first, 1).template toAdd<double>() * manager->getRange(x.second).template toAdd<double>() + manager->getEncoding(x.second, 1).template toAdd<double>() * manager->getRange(x.first).template toAdd<double>();
  931. // Create the ODDs.
  932. storm::dd::Odd rowOdd;
  933. ASSERT_NO_THROW(rowOdd = manager->getRange(x.first).createOdd());
  934. storm::dd::Odd columnOdd;
  935. ASSERT_NO_THROW(columnOdd = manager->getRange(x.second).createOdd());
  936. // Try to translate the matrix.
  937. storm::storage::SparseMatrix<double> matrix;
  938. ASSERT_NO_THROW(matrix = dd.toMatrix({x.first}, {x.second}, rowOdd, columnOdd));
  939. EXPECT_EQ(9ul, matrix.getRowCount());
  940. EXPECT_EQ(9ul, matrix.getColumnCount());
  941. EXPECT_EQ(25ul, matrix.getNonzeroEntryCount());
  942. dd = manager->getRange(x.first).template toAdd<double>() * manager->getRange(x.second).template toAdd<double>() * manager->getEncoding(a.first, 0).ite(dd, dd + manager->template getConstant<double>(1));
  943. ASSERT_NO_THROW(matrix = dd.toMatrix({a.first}, rowOdd, columnOdd));
  944. EXPECT_EQ(18ul, matrix.getRowCount());
  945. EXPECT_EQ(9ul, matrix.getRowGroupCount());
  946. EXPECT_EQ(9ul, matrix.getColumnCount());
  947. EXPECT_EQ(106ul, matrix.getNonzeroEntryCount());
  948. }
  949. TEST(SylvanDd, BddToExpressionTest) {
  950. std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::Sylvan>> ddManager(new storm::dd::DdManager<storm::dd::DdType::Sylvan>());
  951. std::pair<storm::expressions::Variable, storm::expressions::Variable> a = ddManager->addMetaVariable("a");
  952. std::pair<storm::expressions::Variable, storm::expressions::Variable> b = ddManager->addMetaVariable("b");
  953. storm::dd::Bdd<storm::dd::DdType::Sylvan> bdd = ddManager->getBddOne();
  954. bdd &= ddManager->getEncoding(a.first, 1);
  955. bdd |= ddManager->getEncoding(b.first, 0);
  956. std::shared_ptr<storm::expressions::ExpressionManager> manager = std::make_shared<storm::expressions::ExpressionManager>();
  957. storm::expressions::Variable c = manager->declareBooleanVariable("c");
  958. storm::expressions::Variable d = manager->declareBooleanVariable("d");
  959. auto result = bdd.toExpression(*manager);
  960. }