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.

1048 lines
34 KiB

  1. #include <stdint.h>
  2. #include <math.h>
  3. #include "sylvan_int.h"
  4. #include "storm_wrapper.h"
  5. #include "sylvan_mtbdd_storm.h"
  6. // Import the types created for rational numbers and functions.
  7. extern uint32_t srn_type;
  8. extern uint32_t srf_type;
  9. /**
  10. * Binary operation Times (for MTBDDs of same type)
  11. * Only for MTBDDs where either all leaves are Integer or Double.
  12. * If either operand is mtbdd_false (not defined),
  13. * then the result is mtbdd_false (i.e. not defined).
  14. */
  15. TASK_IMPL_2(MTBDD, mtbdd_op_divide, MTBDD*, pa, MTBDD*, pb)
  16. {
  17. MTBDD a = *pa, b = *pb;
  18. if (a == mtbdd_false || b == mtbdd_false) return mtbdd_false;
  19. // Do not handle Boolean MTBDDs...
  20. mtbddnode_t na = MTBDD_GETNODE(a);
  21. mtbddnode_t nb = MTBDD_GETNODE(b);
  22. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  23. uint64_t val_a = mtbddnode_getvalue(na);
  24. uint64_t val_b = mtbddnode_getvalue(nb);
  25. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  26. int64_t va = *(int64_t*)(&val_a);
  27. int64_t vb = *(int64_t*)(&val_b);
  28. if (va == 0) return a;
  29. else if (vb == 0) return b;
  30. else {
  31. MTBDD result;
  32. if (va == 1) result = b;
  33. else if (vb == 1) result = a;
  34. else result = mtbdd_int64(va*vb);
  35. return result;
  36. }
  37. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  38. // both double
  39. double vval_a = *(double*)&val_a;
  40. double vval_b = *(double*)&val_b;
  41. if (vval_a == 0.0) return a;
  42. else if (vval_b == 0.0) {
  43. if (vval_a > 0.0) {
  44. return mtbdd_double(INFINITY);
  45. } else {
  46. return mtbdd_double(-INFINITY);
  47. }
  48. return b;
  49. } else {
  50. MTBDD result;
  51. if (vval_b == 1.0) result = a;
  52. result = mtbdd_double(vval_a / vval_b);
  53. return result;
  54. }
  55. }
  56. else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  57. // both fraction
  58. uint64_t nom_a = val_a>>32;
  59. uint64_t nom_b = val_b>>32;
  60. uint64_t denom_a = val_a&0xffffffff;
  61. uint64_t denom_b = val_b&0xffffffff;
  62. // multiply!
  63. uint32_t c = gcd(denom_b, denom_a);
  64. uint32_t d = gcd(nom_a, nom_b);
  65. nom_a /= d;
  66. denom_a /= c;
  67. nom_a *= (denom_b/c);
  68. denom_a *= (nom_b/d);
  69. // compute result
  70. MTBDD result = mtbdd_fraction(nom_a, denom_a);
  71. return result;
  72. }
  73. }
  74. return mtbdd_invalid;
  75. }
  76. /**
  77. * Binary operation Equals (for MTBDDs of same type)
  78. * Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
  79. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  80. * then the result is mtbdd_false (i.e. not defined).
  81. */
  82. TASK_IMPL_2(MTBDD, mtbdd_op_equals, MTBDD*, pa, MTBDD*, pb)
  83. {
  84. MTBDD a = *pa, b = *pb;
  85. if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
  86. if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
  87. mtbddnode_t na = MTBDD_GETNODE(a);
  88. mtbddnode_t nb = MTBDD_GETNODE(b);
  89. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  90. uint64_t val_a = mtbddnode_getvalue(na);
  91. uint64_t val_b = mtbddnode_getvalue(nb);
  92. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  93. int64_t va = *(int64_t*)(&val_a);
  94. int64_t vb = *(int64_t*)(&val_b);
  95. if (va == vb) return mtbdd_true;
  96. return mtbdd_false;
  97. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  98. // both double
  99. double vval_a = *(double*)&val_a;
  100. double vval_b = *(double*)&val_b;
  101. if (vval_a == vval_b) return mtbdd_true;
  102. return mtbdd_false;
  103. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  104. // both fraction
  105. uint64_t nom_a = val_a>>32;
  106. uint64_t nom_b = val_b>>32;
  107. uint64_t denom_a = val_a&0xffffffff;
  108. uint64_t denom_b = val_b&0xffffffff;
  109. if (nom_a == nom_b && denom_a == denom_b) return mtbdd_true;
  110. return mtbdd_false;
  111. }
  112. }
  113. if (a < b) {
  114. *pa = b;
  115. *pb = a;
  116. }
  117. return mtbdd_invalid;
  118. }
  119. /**
  120. * Binary operation Equals (for MTBDDs of same type)
  121. * Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
  122. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  123. * then the result is mtbdd_false (i.e. not defined).
  124. */
  125. TASK_IMPL_2(MTBDD, mtbdd_op_less, MTBDD*, pa, MTBDD*, pb)
  126. {
  127. MTBDD a = *pa, b = *pb;
  128. if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
  129. if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
  130. mtbddnode_t na = MTBDD_GETNODE(a);
  131. mtbddnode_t nb = MTBDD_GETNODE(b);
  132. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  133. uint64_t val_a = mtbddnode_getvalue(na);
  134. uint64_t val_b = mtbddnode_getvalue(nb);
  135. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  136. int64_t va = *(int64_t*)(&val_a);
  137. int64_t vb = *(int64_t*)(&val_b);
  138. if (va < vb) return mtbdd_true;
  139. return mtbdd_false;
  140. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  141. // both double
  142. double vval_a = *(double*)&val_a;
  143. double vval_b = *(double*)&val_b;
  144. if (vval_a < vval_b) return mtbdd_true;
  145. return mtbdd_false;
  146. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  147. // both fraction
  148. uint64_t nom_a = val_a>>32;
  149. uint64_t nom_b = val_b>>32;
  150. uint64_t denom_a = val_a&0xffffffff;
  151. uint64_t denom_b = val_b&0xffffffff;
  152. return nom_a * denom_b < nom_b * denom_a ? mtbdd_true : mtbdd_false;
  153. }
  154. }
  155. return mtbdd_invalid;
  156. }
  157. /**
  158. * Binary operation Less or Equals (for MTBDDs of same type)
  159. * Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
  160. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  161. * then the result is mtbdd_false (i.e. not defined).
  162. */
  163. TASK_IMPL_2(MTBDD, mtbdd_op_less_or_equal, MTBDD*, pa, MTBDD*, pb)
  164. {
  165. MTBDD a = *pa, b = *pb;
  166. if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
  167. if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
  168. mtbddnode_t na = MTBDD_GETNODE(a);
  169. mtbddnode_t nb = MTBDD_GETNODE(b);
  170. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  171. uint64_t val_a = mtbddnode_getvalue(na);
  172. uint64_t val_b = mtbddnode_getvalue(nb);
  173. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  174. int64_t va = *(int64_t*)(&val_a);
  175. int64_t vb = *(int64_t*)(&val_b);
  176. return va <= vb ? mtbdd_true : mtbdd_false;
  177. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  178. // both double
  179. double vval_a = *(double*)&val_a;
  180. double vval_b = *(double*)&val_b;
  181. if (vval_a <= vval_b) return mtbdd_true;
  182. return mtbdd_false;
  183. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  184. // both fraction
  185. uint64_t nom_a = val_a>>32;
  186. uint64_t nom_b = val_b>>32;
  187. uint64_t denom_a = val_a&0xffffffff;
  188. uint64_t denom_b = val_b&0xffffffff;
  189. nom_a *= denom_b;
  190. nom_b *= denom_a;
  191. return nom_a <= nom_b ? mtbdd_true : mtbdd_false;
  192. }
  193. }
  194. return mtbdd_invalid;
  195. }
  196. /**
  197. * Binary operation Greater or Equals (for MTBDDs of same type)
  198. * Only for MTBDDs where either all leaves are Boolean, or Integer, or Double.
  199. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  200. * then the result is mtbdd_false (i.e. not defined).
  201. */
  202. TASK_IMPL_2(MTBDD, mtbdd_op_greater_or_equal, MTBDD*, pa, MTBDD*, pb)
  203. {
  204. MTBDD a = *pa, b = *pb;
  205. if (a == mtbdd_false && b == mtbdd_false) return mtbdd_true;
  206. if (a == mtbdd_true && b == mtbdd_true) return mtbdd_true;
  207. mtbddnode_t na = MTBDD_GETNODE(a);
  208. mtbddnode_t nb = MTBDD_GETNODE(b);
  209. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  210. uint64_t val_a = mtbddnode_getvalue(na);
  211. uint64_t val_b = mtbddnode_getvalue(nb);
  212. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  213. int64_t va = *(int64_t*)(&val_a);
  214. int64_t vb = *(int64_t*)(&val_b);
  215. return va >= vb ? mtbdd_true : mtbdd_false;
  216. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  217. // both double
  218. double vval_a = *(double*)&val_a;
  219. double vval_b = *(double*)&val_b;
  220. if (vval_a >= vval_b) return mtbdd_true;
  221. return mtbdd_false;
  222. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  223. // both fraction
  224. uint64_t nom_a = val_a>>32;
  225. uint64_t nom_b = val_b>>32;
  226. uint64_t denom_a = val_a&0xffffffff;
  227. uint64_t denom_b = val_b&0xffffffff;
  228. nom_a *= denom_b;
  229. nom_b *= denom_a;
  230. return nom_a >= nom_b ? mtbdd_true : mtbdd_false;
  231. }
  232. }
  233. return mtbdd_invalid;
  234. }
  235. /**
  236. * Binary operation Pow (for MTBDDs of same type)
  237. * Only for MTBDDs where either all leaves are Double.
  238. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  239. * then the result is mtbdd_false (i.e. not defined).
  240. */
  241. TASK_IMPL_2(MTBDD, mtbdd_op_pow, MTBDD*, pa, MTBDD*, pb)
  242. {
  243. MTBDD a = *pa, b = *pb;
  244. mtbddnode_t na = MTBDD_GETNODE(a);
  245. mtbddnode_t nb = MTBDD_GETNODE(b);
  246. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  247. uint64_t val_a = mtbddnode_getvalue(na);
  248. uint64_t val_b = mtbddnode_getvalue(nb);
  249. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  250. assert(0);
  251. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  252. // both double
  253. double vval_a = *(double*)&val_a;
  254. double vval_b = *(double*)&val_b;
  255. return mtbdd_double(pow(vval_a, vval_b));
  256. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  257. assert(0);
  258. }
  259. }
  260. return mtbdd_invalid;
  261. }
  262. /**
  263. * Binary operation Mod (for MTBDDs of same type)
  264. * Only for MTBDDs where either all leaves are Double.
  265. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  266. * then the result is mtbdd_false (i.e. not defined).
  267. */
  268. TASK_IMPL_2(MTBDD, mtbdd_op_mod, MTBDD*, pa, MTBDD*, pb)
  269. {
  270. MTBDD a = *pa, b = *pb;
  271. mtbddnode_t na = MTBDD_GETNODE(a);
  272. mtbddnode_t nb = MTBDD_GETNODE(b);
  273. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  274. uint64_t val_a = mtbddnode_getvalue(na);
  275. uint64_t val_b = mtbddnode_getvalue(nb);
  276. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  277. assert(0);
  278. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  279. // both double
  280. double vval_a = *(double*)&val_a;
  281. double vval_b = *(double*)&val_b;
  282. return mtbdd_double(fmod(vval_a, vval_b));
  283. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  284. assert(0);
  285. }
  286. }
  287. return mtbdd_invalid;
  288. }
  289. /**
  290. * Binary operation Log (for MTBDDs of same type)
  291. * Only for MTBDDs where either all leaves are Double.
  292. * For Integer/Double MTBDD, if either operand is mtbdd_false (not defined),
  293. * then the result is mtbdd_false (i.e. not defined).
  294. */
  295. TASK_IMPL_2(MTBDD, mtbdd_op_logxy, MTBDD*, pa, MTBDD*, pb)
  296. {
  297. MTBDD a = *pa, b = *pb;
  298. mtbddnode_t na = MTBDD_GETNODE(a);
  299. mtbddnode_t nb = MTBDD_GETNODE(b);
  300. if (mtbddnode_isleaf(na) && mtbddnode_isleaf(nb)) {
  301. uint64_t val_a = mtbddnode_getvalue(na);
  302. uint64_t val_b = mtbddnode_getvalue(nb);
  303. if (mtbddnode_gettype(na) == 0 && mtbddnode_gettype(nb) == 0) {
  304. assert(0);
  305. } else if (mtbddnode_gettype(na) == 1 && mtbddnode_gettype(nb) == 1) {
  306. // both double
  307. double vval_a = *(double*)&val_a;
  308. double vval_b = *(double*)&val_b;
  309. return mtbdd_double(log(vval_a) / log(vval_b));
  310. } else if (mtbddnode_gettype(na) == 2 && mtbddnode_gettype(nb) == 2) {
  311. assert(0);
  312. }
  313. }
  314. return mtbdd_invalid;
  315. }
  316. TASK_IMPL_2(MTBDD, mtbdd_op_not_zero, MTBDD, a, size_t, v)
  317. {
  318. /* We only expect "double" terminals, or false */
  319. if (a == mtbdd_false) return mtbdd_false;
  320. if (a == mtbdd_true) return mtbdd_true;
  321. // a != constant
  322. mtbddnode_t na = MTBDD_GETNODE(a);
  323. if (mtbddnode_isleaf(na)) {
  324. if (mtbddnode_gettype(na) == 0) {
  325. return mtbdd_getint64(a) != 0 ? mtbdd_true : mtbdd_false;
  326. } else if (mtbddnode_gettype(na) == 1) {
  327. return mtbdd_getdouble(a) != 0.0 ? mtbdd_true : mtbdd_false;
  328. } else if (mtbddnode_gettype(na) == 2) {
  329. return mtbdd_getnumer(a) != 0 ? mtbdd_true : mtbdd_false;
  330. } else if (mtbddnode_gettype(na) == srn_type) {
  331. return storm_rational_number_is_zero((storm_rational_number_ptr)mtbdd_getvalue(a)) == 0 ? mtbdd_true : mtbdd_false;
  332. }
  333. #if defined(SYLVAN_HAVE_CARL) || defined(STORM_HAVE_CARL)
  334. else if (mtbddnode_gettype(na) == srf_type) {
  335. return storm_rational_function_is_zero((storm_rational_function_ptr)mtbdd_getvalue(a)) == 0 ? mtbdd_true : mtbdd_false;
  336. }
  337. #endif
  338. }
  339. // Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
  340. (void)v;
  341. return mtbdd_invalid;
  342. }
  343. TASK_IMPL_1(MTBDD, mtbdd_not_zero, MTBDD, dd)
  344. {
  345. return mtbdd_uapply(dd, TASK(mtbdd_op_not_zero), 0);
  346. }
  347. TASK_IMPL_2(MTBDD, mtbdd_op_floor, MTBDD, a, size_t, v)
  348. {
  349. /* We only expect "double" terminals, or false */
  350. if (a == mtbdd_false) return mtbdd_false;
  351. if (a == mtbdd_true) return mtbdd_true;
  352. // a != constant
  353. mtbddnode_t na = MTBDD_GETNODE(a);
  354. if (mtbddnode_isleaf(na)) {
  355. if (mtbddnode_gettype(na) == 0) {
  356. return a;
  357. } else if (mtbddnode_gettype(na) == 1) {
  358. MTBDD result = mtbdd_double(floor(mtbdd_getdouble(a)));
  359. return result;
  360. } else if (mtbddnode_gettype(na) == 2) {
  361. MTBDD result = mtbdd_fraction(mtbdd_getnumer(a) / mtbdd_getdenom(a), 1);
  362. return result;
  363. }
  364. }
  365. // Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
  366. (void)v;
  367. return mtbdd_invalid;
  368. }
  369. TASK_IMPL_1(MTBDD, mtbdd_floor, MTBDD, dd)
  370. {
  371. return mtbdd_uapply(dd, TASK(mtbdd_op_floor), 0);
  372. }
  373. TASK_IMPL_2(MTBDD, mtbdd_op_ceil, MTBDD, a, size_t, v)
  374. {
  375. /* We only expect "double" terminals, or false */
  376. if (a == mtbdd_false) return mtbdd_false;
  377. if (a == mtbdd_true) return mtbdd_true;
  378. // a != constant
  379. mtbddnode_t na = MTBDD_GETNODE(a);
  380. if (mtbddnode_isleaf(na)) {
  381. if (mtbddnode_gettype(na) == 0) {
  382. return a;
  383. } else if (mtbddnode_gettype(na) == 1) {
  384. MTBDD result = mtbdd_double(ceil(mtbdd_getdouble(a)));
  385. return result;
  386. } else if (mtbddnode_gettype(na) == 2) {
  387. MTBDD result = mtbdd_fraction(mtbdd_getnumer(a) / mtbdd_getdenom(a) + 1, 1);
  388. return result;
  389. }
  390. }
  391. // Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
  392. (void)v;
  393. return mtbdd_invalid;
  394. }
  395. TASK_IMPL_1(MTBDD, mtbdd_ceil, MTBDD, dd)
  396. {
  397. return mtbdd_uapply(dd, TASK(mtbdd_op_ceil), 0);
  398. }
  399. TASK_IMPL_2(MTBDD, mtbdd_op_bool_to_double, MTBDD, a, size_t, v)
  400. {
  401. /* We only expect "double" terminals, or false */
  402. if (a == mtbdd_false) return mtbdd_double(0);
  403. if (a == mtbdd_true) return mtbdd_double(1.0);
  404. // Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
  405. (void)v;
  406. return mtbdd_invalid;
  407. }
  408. TASK_IMPL_1(MTBDD, mtbdd_bool_to_double, MTBDD, dd)
  409. {
  410. return mtbdd_uapply(dd, TASK(mtbdd_op_bool_to_double), 0);
  411. }
  412. TASK_IMPL_2(MTBDD, mtbdd_op_bool_to_int64, MTBDD, a, size_t, v)
  413. {
  414. /* We only expect "double" terminals, or false */
  415. if (a == mtbdd_false) return mtbdd_int64(0);
  416. if (a == mtbdd_true) return mtbdd_int64(1);
  417. // Ugly hack to get rid of the error "unused variable v" (because there is no version of uapply without a parameter).
  418. (void)v;
  419. return mtbdd_invalid;
  420. }
  421. TASK_IMPL_1(MTBDD, mtbdd_bool_to_int64, MTBDD, dd)
  422. {
  423. return mtbdd_uapply(dd, TASK(mtbdd_op_bool_to_int64), 0);
  424. }
  425. /**
  426. * Calculate the number of satisfying variable assignments according to <variables>.
  427. */
  428. TASK_IMPL_2(double, mtbdd_non_zero_count, MTBDD, dd, size_t, nvars)
  429. {
  430. /* Trivial cases */
  431. if (dd == mtbdd_false) return 0.0;
  432. mtbddnode_t na = MTBDD_GETNODE(dd);
  433. if (mtbdd_isleaf(dd)) {
  434. if (mtbddnode_gettype(na) == 0) {
  435. return mtbdd_getint64(dd) != 0 ? powl(2.0L, nvars) : 0.0;
  436. } else if (mtbddnode_gettype(na) == 1) {
  437. return mtbdd_getdouble(dd) != 0 ? powl(2.0L, nvars) : 0.0;
  438. } else if (mtbddnode_gettype(na) == 2) {
  439. return mtbdd_getnumer(dd) != 0 ? powl(2.0L, nvars) : 0.0;
  440. } else if (mtbddnode_gettype(na) == srn_type) {
  441. return storm_rational_number_is_zero((storm_rational_number_ptr)mtbdd_getvalue(dd)) == 0 ? powl(2.0L, nvars) : 0.0;
  442. }
  443. #if defined(SYLVAN_HAVE_CARL) || defined(STORM_HAVE_CARL)
  444. else if (mtbddnode_gettype(na) == srf_type) {
  445. return storm_rational_function_is_zero((storm_rational_function_ptr)mtbdd_getvalue(dd)) == 0 ? powl(2.0L, nvars) : 0.0;
  446. }
  447. #endif
  448. }
  449. /* Perhaps execute garbage collection */
  450. sylvan_gc_test();
  451. union {
  452. double d;
  453. uint64_t s;
  454. } hack;
  455. /* Consult cache */
  456. if (cache_get3(CACHE_MTBDD_NONZERO_COUNT, dd, 0, nvars, &hack.s)) {
  457. sylvan_stats_count(CACHE_MTBDD_NONZERO_COUNT);
  458. return hack.d;
  459. }
  460. SPAWN(mtbdd_non_zero_count, mtbdd_gethigh(dd), nvars-1);
  461. double low = CALL(mtbdd_non_zero_count, mtbdd_getlow(dd), nvars-1);
  462. hack.d = low + SYNC(mtbdd_non_zero_count);
  463. cache_put3(CACHE_MTBDD_NONZERO_COUNT, dd, 0, nvars, hack.s);
  464. return hack.d;
  465. }
  466. int mtbdd_iszero(MTBDD dd) {
  467. if (mtbdd_gettype(dd) == 0) {
  468. return mtbdd_getint64(dd) == 0;
  469. } else if (mtbdd_gettype(dd) == 1) {
  470. return mtbdd_getdouble(dd) == 0;
  471. } else if (mtbdd_gettype(dd) == 2) {
  472. return mtbdd_getnumer(dd) == 0;
  473. } else if (mtbdd_gettype(dd) == srn_type) {
  474. return storm_rational_number_is_zero((storm_rational_number_ptr)mtbdd_getvalue(dd)) == 1 ? 1 : 0;
  475. }
  476. #if defined(SYLVAN_HAVE_CARL) || defined(STORM_HAVE_CARL)
  477. else if (mtbdd_gettype(dd) == srf_type) {
  478. return storm_rational_function_is_zero((storm_rational_function_ptr)mtbdd_getvalue(dd)) == 1 ? 1 : 0;
  479. }
  480. #endif
  481. return 0;
  482. }
  483. int mtbdd_isnonzero(MTBDD dd) {
  484. return mtbdd_iszero(dd) ? 0 : 1;
  485. }
  486. TASK_IMPL_2(MTBDD, mtbdd_op_complement, MTBDD, a, size_t, k)
  487. {
  488. // if a is false, then it is a partial function. Keep partial!
  489. if (a == mtbdd_false) return mtbdd_false;
  490. // a != constant
  491. mtbddnode_t na = MTBDD_GETNODE(a);
  492. if (mtbddnode_isleaf(na)) {
  493. if (mtbddnode_gettype(na) == 0) {
  494. int64_t v = mtbdd_getint64(a);
  495. if (v == 0) {
  496. return mtbdd_int64(1);
  497. } else {
  498. return mtbdd_int64(0);
  499. }
  500. } else if (mtbddnode_gettype(na) == 1) {
  501. double d = mtbdd_getdouble(a);
  502. if (d == 0.0) {
  503. return mtbdd_double(1.0);
  504. } else {
  505. return mtbdd_double(0.0);
  506. }
  507. } else if (mtbddnode_gettype(na) == 2) {
  508. printf("ERROR: mtbdd_op_complement type FRACTION.\n");
  509. assert(0);
  510. }
  511. }
  512. return mtbdd_invalid;
  513. (void)k; // unused variable
  514. }
  515. #include "sylvan_storm_rational_number.h"
  516. TASK_IMPL_2(MTBDD, mtbdd_op_sharpen, MTBDD, a, size_t, p)
  517. {
  518. /* We only expect double or rational number terminals, or false */
  519. if (a == mtbdd_false) return mtbdd_false;
  520. if (a == mtbdd_true) return mtbdd_true;
  521. // a != constant
  522. mtbddnode_t na = MTBDD_GETNODE(a);
  523. if (mtbddnode_isleaf(na)) {
  524. if (mtbddnode_gettype(na) == 1) {
  525. storm_rational_number_ptr rnp = storm_double_sharpen(mtbdd_getdouble(a), p);
  526. // If the sharpening failed, we return mtbdd_false so this can be detected at the top level.
  527. if (rnp == (storm_rational_number_ptr)0) {
  528. return mtbdd_false;
  529. }
  530. MTBDD result = mtbdd_storm_rational_number(rnp);
  531. return result;
  532. } else if (mtbddnode_gettype(na) == srn_type) {
  533. return mtbdd_storm_rational_number(storm_rational_number_sharpen((storm_rational_number_ptr)mtbdd_getstorm_rational_number_ptr(a), p));
  534. } else {
  535. printf("ERROR: Unsupported value type in sharpen.\n");
  536. assert(0);
  537. }
  538. }
  539. return mtbdd_invalid;
  540. }
  541. TASK_IMPL_2(MTBDD, mtbdd_sharpen, MTBDD, dd, size_t, p)
  542. {
  543. return mtbdd_uapply_fail_false(dd, TASK(mtbdd_op_sharpen), p);
  544. }
  545. TASK_IMPL_2(MTBDD, mtbdd_op_to_rational_number, MTBDD, a, size_t, p)
  546. {
  547. /* We only expect double or rational number terminals, or false */
  548. if (a == mtbdd_false) return mtbdd_false;
  549. if (a == mtbdd_true) return mtbdd_true;
  550. // a != constant
  551. mtbddnode_t na = MTBDD_GETNODE(a);
  552. if (mtbddnode_isleaf(na)) {
  553. if (mtbddnode_gettype(na) == 1) {
  554. MTBDD result = mtbdd_storm_rational_number(storm_rational_number_from_double(mtbdd_getdouble(a)));
  555. return result;
  556. } else {
  557. printf("ERROR: Unsupported value type in conversion to rational number.\n");
  558. assert(0);
  559. }
  560. }
  561. return mtbdd_invalid;
  562. (void)p; // unused variable
  563. }
  564. TASK_IMPL_2(MTBDD, mtbdd_to_rational_number, MTBDD, dd, size_t, p)
  565. {
  566. return mtbdd_uapply(dd, TASK(mtbdd_op_to_rational_number), 0);
  567. }
  568. TASK_IMPL_3(BDD, mtbdd_min_abstract_representative, MTBDD, a, BDD, v, BDDVAR, prev_level) {
  569. /* Maybe perform garbage collection */
  570. sylvan_gc_test();
  571. if (sylvan_set_isempty(v)) {
  572. return sylvan_true;
  573. }
  574. /* Cube is guaranteed to be a cube at this point. */
  575. if (mtbdd_isleaf(a)) {
  576. BDD _v = sylvan_set_next(v);
  577. BDD res = CALL(mtbdd_min_abstract_representative, a, _v, prev_level);
  578. if (res == sylvan_invalid) {
  579. return sylvan_invalid;
  580. }
  581. sylvan_ref(res);
  582. BDD res1 = sylvan_not(sylvan_ite(sylvan_ithvar(bddnode_getvariable(MTBDD_GETNODE(v))), sylvan_true, sylvan_not(res)));
  583. if (res1 == sylvan_invalid) {
  584. sylvan_deref(res);
  585. return sylvan_invalid;
  586. }
  587. sylvan_deref(res);
  588. return res1;
  589. }
  590. /* Check cache */
  591. MTBDD result;
  592. if (cache_get3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)1, &result)) {
  593. sylvan_stats_count(MTBDD_ABSTRACT_CACHED);
  594. return result;
  595. }
  596. mtbddnode_t na = MTBDD_GETNODE(a);
  597. uint32_t va = mtbddnode_getvariable(na);
  598. bddnode_t nv = MTBDD_GETNODE(v);
  599. BDDVAR vv = bddnode_getvariable(nv);
  600. /* Abstract a variable that does not appear in a. */
  601. if (va > vv) {
  602. BDD _v = sylvan_set_next(v);
  603. BDD res = CALL(mtbdd_min_abstract_representative, a, _v, va);
  604. if (res == sylvan_invalid) {
  605. return sylvan_invalid;
  606. }
  607. // Fill in the missing variables to make representative unique.
  608. sylvan_ref(res);
  609. BDD res1 = sylvan_ite(sylvan_ithvar(vv), sylvan_false, res);
  610. if (res1 == sylvan_invalid) {
  611. sylvan_deref(res);
  612. return sylvan_invalid;
  613. }
  614. sylvan_deref(res);
  615. return res1;
  616. }
  617. MTBDD E = mtbdd_getlow(a);
  618. MTBDD T = mtbdd_gethigh(a);
  619. /* If the two indices are the same, so are their levels. */
  620. if (va == vv) {
  621. BDD _v = sylvan_set_next(v);
  622. BDD res1 = CALL(mtbdd_min_abstract_representative, E, _v, va);
  623. if (res1 == sylvan_invalid) {
  624. return sylvan_invalid;
  625. }
  626. sylvan_ref(res1);
  627. BDD res2 = CALL(mtbdd_min_abstract_representative, T, _v, va);
  628. if (res2 == sylvan_invalid) {
  629. sylvan_deref(res1);
  630. return sylvan_invalid;
  631. }
  632. sylvan_ref(res2);
  633. MTBDD left = mtbdd_abstract_min(E, _v);
  634. if (left == mtbdd_invalid) {
  635. sylvan_deref(res1);
  636. sylvan_deref(res2);
  637. return sylvan_invalid;
  638. }
  639. mtbdd_ref(left);
  640. MTBDD right = mtbdd_abstract_min(T, _v);
  641. if (right == mtbdd_invalid) {
  642. sylvan_deref(res1);
  643. sylvan_deref(res2);
  644. mtbdd_deref(left);
  645. return sylvan_invalid;
  646. }
  647. mtbdd_ref(right);
  648. BDD tmp = mtbdd_less_or_equal_as_bdd(left, right);
  649. if (tmp == sylvan_invalid) {
  650. sylvan_deref(res1);
  651. sylvan_deref(res2);
  652. mtbdd_deref(left);
  653. mtbdd_deref(right);
  654. return sylvan_invalid;
  655. }
  656. sylvan_ref(tmp);
  657. mtbdd_deref(left);
  658. mtbdd_deref(right);
  659. BDD res1Inf = sylvan_ite(tmp, res1, sylvan_false);
  660. if (res1Inf == sylvan_invalid) {
  661. sylvan_deref(res1);
  662. sylvan_deref(res2);
  663. sylvan_deref(tmp);
  664. return sylvan_invalid;
  665. }
  666. sylvan_ref(res1Inf);
  667. sylvan_deref(res1);
  668. BDD res2Inf = sylvan_ite(tmp, sylvan_false, res2);
  669. if (res2Inf == sylvan_invalid) {
  670. sylvan_deref(res2);
  671. sylvan_deref(res1Inf);
  672. sylvan_deref(tmp);
  673. return sylvan_invalid;
  674. }
  675. sylvan_ref(res2Inf);
  676. sylvan_deref(res2);
  677. sylvan_deref(tmp);
  678. BDD res = (res1Inf == res2Inf) ? sylvan_ite(sylvan_ithvar(va), sylvan_false, res1Inf) : sylvan_ite(sylvan_ithvar(va), res2Inf, res1Inf);
  679. if (res == sylvan_invalid) {
  680. sylvan_deref(res1Inf);
  681. sylvan_deref(res2Inf);
  682. return sylvan_invalid;
  683. }
  684. sylvan_ref(res);
  685. sylvan_deref(res1Inf);
  686. sylvan_deref(res2Inf);
  687. /* Store in cache */
  688. if (cache_put3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)1, res)) {
  689. sylvan_stats_count(MTBDD_ABSTRACT_CACHEDPUT);
  690. }
  691. sylvan_deref(res);
  692. return res;
  693. }
  694. else { /* if (va < vv) */
  695. BDD res1 = CALL(mtbdd_min_abstract_representative, E, v, va);
  696. if (res1 == sylvan_invalid) {
  697. return sylvan_invalid;
  698. }
  699. sylvan_ref(res1);
  700. BDD res2 = CALL(mtbdd_min_abstract_representative, T, v, va);
  701. if (res2 == sylvan_invalid) {
  702. sylvan_deref(res1);
  703. return sylvan_invalid;
  704. }
  705. sylvan_ref(res2);
  706. BDD res = (res1 == res2) ? res1 : sylvan_ite(sylvan_ithvar(va), res2, res1);
  707. if (res == sylvan_invalid) {
  708. sylvan_deref(res1);
  709. sylvan_deref(res2);
  710. return sylvan_invalid;
  711. }
  712. sylvan_deref(res1);
  713. sylvan_deref(res2);
  714. /* Store in cache */
  715. if (cache_put3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)1, res)) {
  716. sylvan_stats_count(MTBDD_ABSTRACT_CACHEDPUT);
  717. }
  718. return res;
  719. }
  720. }
  721. TASK_IMPL_3(BDD, mtbdd_max_abstract_representative, MTBDD, a, MTBDD, v, uint32_t, prev_level) {
  722. /* Maybe perform garbage collection */
  723. sylvan_gc_test();
  724. if (sylvan_set_isempty(v)) {
  725. return sylvan_true;
  726. }
  727. /* Count operation */
  728. sylvan_stats_count(MTBDD_ABSTRACT);
  729. /* Cube is guaranteed to be a cube at this point. */
  730. if (mtbdd_isleaf(a)) {
  731. /* Compute result */
  732. BDD _v = sylvan_set_next(v);
  733. BDD res = CALL(mtbdd_max_abstract_representative, a, _v, prev_level);
  734. if (res == sylvan_invalid) {
  735. return sylvan_invalid;
  736. }
  737. sylvan_ref(res);
  738. BDD res1 = sylvan_not(sylvan_ite(sylvan_ithvar(bddnode_getvariable(MTBDD_GETNODE(v))), sylvan_true, sylvan_not(res)));
  739. if (res1 == sylvan_invalid) {
  740. sylvan_deref(res);
  741. return sylvan_invalid;
  742. }
  743. sylvan_deref(res);
  744. return res1;
  745. }
  746. /* Check cache */
  747. MTBDD result;
  748. if (cache_get3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)0, &result)) {
  749. sylvan_stats_count(MTBDD_ABSTRACT_CACHED);
  750. return result;
  751. }
  752. mtbddnode_t na = MTBDD_GETNODE(a);
  753. uint32_t va = mtbddnode_getvariable(na);
  754. bddnode_t nv = MTBDD_GETNODE(v);
  755. BDDVAR vv = bddnode_getvariable(nv);
  756. /* Abstract a variable that does not appear in a. */
  757. if (vv < va) {
  758. BDD _v = sylvan_set_next(v);
  759. BDD res = CALL(mtbdd_max_abstract_representative, a, _v, va);
  760. if (res == sylvan_invalid) {
  761. return sylvan_invalid;
  762. }
  763. // Fill in the missing variables to make representative unique.
  764. sylvan_ref(res);
  765. BDD res1 = sylvan_ite(sylvan_ithvar(vv), sylvan_false, res);
  766. if (res1 == sylvan_invalid) {
  767. sylvan_deref(res);
  768. return sylvan_invalid;
  769. }
  770. sylvan_deref(res);
  771. return res1;
  772. }
  773. MTBDD E = mtbdd_getlow(a);
  774. MTBDD T = mtbdd_gethigh(a);
  775. /* If the two indices are the same, so are their levels. */
  776. if (va == vv) {
  777. BDD _v = sylvan_set_next(v);
  778. BDD res1 = CALL(mtbdd_max_abstract_representative, E, _v, va);
  779. if (res1 == sylvan_invalid) {
  780. return sylvan_invalid;
  781. }
  782. sylvan_ref(res1);
  783. BDD res2 = CALL(mtbdd_max_abstract_representative, T, _v, va);
  784. if (res2 == sylvan_invalid) {
  785. sylvan_deref(res1);
  786. return sylvan_invalid;
  787. }
  788. sylvan_ref(res2);
  789. MTBDD left = mtbdd_abstract_max(E, _v);
  790. if (left == mtbdd_invalid) {
  791. sylvan_deref(res1);
  792. sylvan_deref(res2);
  793. return sylvan_invalid;
  794. }
  795. mtbdd_ref(left);
  796. MTBDD right = mtbdd_abstract_max(T, _v);
  797. if (right == mtbdd_invalid) {
  798. sylvan_deref(res1);
  799. sylvan_deref(res2);
  800. mtbdd_deref(left);
  801. return sylvan_invalid;
  802. }
  803. mtbdd_ref(right);
  804. BDD tmp = mtbdd_greater_or_equal_as_bdd(left, right);
  805. if (tmp == sylvan_invalid) {
  806. sylvan_deref(res1);
  807. sylvan_deref(res2);
  808. mtbdd_deref(left);
  809. mtbdd_deref(right);
  810. return sylvan_invalid;
  811. }
  812. sylvan_ref(tmp);
  813. mtbdd_deref(left);
  814. mtbdd_deref(right);
  815. BDD res1Inf = sylvan_ite(tmp, res1, sylvan_false);
  816. if (res1Inf == sylvan_invalid) {
  817. sylvan_deref(res1);
  818. sylvan_deref(res2);
  819. sylvan_deref(tmp);
  820. return sylvan_invalid;
  821. }
  822. sylvan_ref(res1Inf);
  823. sylvan_deref(res1);
  824. BDD res2Inf = sylvan_ite(tmp, sylvan_false, res2);
  825. if (res2Inf == sylvan_invalid) {
  826. sylvan_deref(res2);
  827. sylvan_deref(res1Inf);
  828. sylvan_deref(tmp);
  829. return sylvan_invalid;
  830. }
  831. sylvan_ref(res2Inf);
  832. sylvan_deref(res2);
  833. sylvan_deref(tmp);
  834. BDD res = (res1Inf == res2Inf) ? sylvan_ite(sylvan_ithvar(va), sylvan_false, res1Inf) : sylvan_ite(sylvan_ithvar(va), res2Inf, res1Inf);
  835. if (res == sylvan_invalid) {
  836. sylvan_deref(res1Inf);
  837. sylvan_deref(res2Inf);
  838. return sylvan_invalid;
  839. }
  840. sylvan_ref(res);
  841. sylvan_deref(res1Inf);
  842. sylvan_deref(res2Inf);
  843. /* Store in cache */
  844. if (cache_put3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)0, res)) {
  845. sylvan_stats_count(MTBDD_ABSTRACT_CACHEDPUT);
  846. }
  847. sylvan_deref(res);
  848. return res;
  849. }
  850. else { /* if (va < vv) */
  851. BDD res1 = CALL(mtbdd_max_abstract_representative, E, v, va);
  852. if (res1 == sylvan_invalid) {
  853. return sylvan_invalid;
  854. }
  855. sylvan_ref(res1);
  856. BDD res2 = CALL(mtbdd_max_abstract_representative, T, v, va);
  857. if (res2 == sylvan_invalid) {
  858. sylvan_deref(res1);
  859. return sylvan_invalid;
  860. }
  861. sylvan_ref(res2);
  862. BDD res = (res1 == res2) ? res1 : sylvan_ite(sylvan_ithvar(va), res2, res1);
  863. if (res == sylvan_invalid) {
  864. sylvan_deref(res1);
  865. sylvan_deref(res2);
  866. return sylvan_invalid;
  867. }
  868. sylvan_deref(res1);
  869. sylvan_deref(res2);
  870. /* Store in cache */
  871. if (cache_put3(CACHE_MTBDD_ABSTRACT_REPRESENTATIVE, a, v, (size_t)0, res)) {
  872. sylvan_stats_count(MTBDD_ABSTRACT_CACHEDPUT);
  873. }
  874. return res;
  875. }
  876. }
  877. TASK_IMPL_3(MTBDD, mtbdd_uapply_nocache, MTBDD, dd, mtbdd_uapply_op, op, size_t, param)
  878. {
  879. /* Maybe perform garbage collection */
  880. sylvan_gc_test();
  881. /* Check cache */
  882. MTBDD result;
  883. // Caching would be done here, but is omitted (as this is the purpose of this function).
  884. /* Check terminal case */
  885. result = WRAP(op, dd, param);
  886. if (result != mtbdd_invalid) {
  887. // Caching would be done here, but is omitted (as this is the purpose of this function).
  888. return result;
  889. }
  890. /* Get cofactors */
  891. mtbddnode_t ndd = MTBDD_GETNODE(dd);
  892. MTBDD ddlow = node_getlow(dd, ndd);
  893. MTBDD ddhigh = node_gethigh(dd, ndd);
  894. /* Recursive */
  895. mtbdd_refs_spawn(SPAWN(mtbdd_uapply_nocache, ddhigh, op, param));
  896. MTBDD low = mtbdd_refs_push(CALL(mtbdd_uapply_nocache, ddlow, op, param));
  897. MTBDD high = mtbdd_refs_sync(SYNC(mtbdd_uapply_nocache));
  898. mtbdd_refs_pop(1);
  899. result = mtbdd_makenode(mtbddnode_getvariable(ndd), low, high);
  900. // Caching would be done here, but is omitted (as this is the purpose of this function).
  901. return result;
  902. }