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.

326 lines
7.4 KiB

  1. /***** ltl2ba : rewrt.c *****/
  2. /* Written by Denis Oddoux, LIAFA, France */
  3. /* Copyright (c) 2001 Denis Oddoux */
  4. /* Modified by Paul Gastin, LSV, France */
  5. /* Copyright (c) 2007 Paul Gastin */
  6. /* */
  7. /* This program is free software; you can redistribute it and/or modify */
  8. /* it under the terms of the GNU General Public License as published by */
  9. /* the Free Software Foundation; either version 2 of the License, or */
  10. /* (at your option) any later version. */
  11. /* */
  12. /* This program is distributed in the hope that it will be useful, */
  13. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  14. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  15. /* GNU General Public License for more details. */
  16. /* */
  17. /* You should have received a copy of the GNU General Public License */
  18. /* along with this program; if not, write to the Free Software */
  19. /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
  20. /* */
  21. /* Based on the translation algorithm by Gastin and Oddoux, */
  22. /* presented at the 13th International Conference on Computer Aided */
  23. /* Verification, CAV 2001, Paris, France. */
  24. /* Proceedings - LNCS 2102, pp. 53-65 */
  25. /* */
  26. /* Send bug-reports and/or questions to Paul Gastin */
  27. /* http://www.lsv.ens-cachan.fr/~gastin */
  28. /* */
  29. /* Some of the code in this file was taken from the Spin software */
  30. /* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A. */
  31. #include "ltl2ba.h"
  32. extern int tl_verbose;
  33. static Node *can = ZN;
  34. Node *
  35. right_linked(Node *n)
  36. {
  37. if (!n) return n;
  38. if (n->ntyp == AND || n->ntyp == OR)
  39. while (n->lft && n->lft->ntyp == n->ntyp)
  40. { Node *tmp = n->lft;
  41. n->lft = tmp->rgt;
  42. tmp->rgt = n;
  43. n = tmp;
  44. }
  45. n->lft = right_linked(n->lft);
  46. n->rgt = right_linked(n->rgt);
  47. return n;
  48. }
  49. Node *
  50. canonical(Node *n)
  51. { Node *m; /* assumes input is right_linked */
  52. if (!n) return n;
  53. if (m = in_cache(n))
  54. return m;
  55. n->rgt = canonical(n->rgt);
  56. n->lft = canonical(n->lft);
  57. return cached(n);
  58. }
  59. Node *
  60. push_negation(Node *n)
  61. { Node *m;
  62. Assert(n->ntyp == NOT, n->ntyp);
  63. switch (n->lft->ntyp) {
  64. case TRUE:
  65. releasenode(0, n->lft);
  66. n->lft = ZN;
  67. n->ntyp = FALSE;
  68. break;
  69. case FALSE:
  70. releasenode(0, n->lft);
  71. n->lft = ZN;
  72. n->ntyp = TRUE;
  73. break;
  74. case NOT:
  75. m = n->lft->lft;
  76. releasenode(0, n->lft);
  77. n->lft = ZN;
  78. releasenode(0, n);
  79. n = m;
  80. break;
  81. case V_OPER:
  82. n->ntyp = U_OPER;
  83. goto same;
  84. case U_OPER:
  85. n->ntyp = V_OPER;
  86. goto same;
  87. #ifdef NXT
  88. case NEXT:
  89. n->ntyp = NEXT;
  90. n->lft->ntyp = NOT;
  91. n->lft = push_negation(n->lft);
  92. break;
  93. #endif
  94. case AND:
  95. n->ntyp = OR;
  96. goto same;
  97. case OR:
  98. n->ntyp = AND;
  99. same: m = n->lft->rgt;
  100. n->lft->rgt = ZN;
  101. n->rgt = Not(m);
  102. n->lft->ntyp = NOT;
  103. m = n->lft;
  104. n->lft = push_negation(m);
  105. break;
  106. }
  107. return rewrite(n);
  108. }
  109. static void
  110. addcan(int tok, Node *n)
  111. { Node *m, *prev = ZN;
  112. Node **ptr;
  113. Node *N;
  114. Symbol *s, *t; int cmp;
  115. if (!n) return;
  116. if (n->ntyp == tok)
  117. { addcan(tok, n->rgt);
  118. addcan(tok, n->lft);
  119. return;
  120. }
  121. #if 0
  122. if ((tok == AND && n->ntyp == TRUE)
  123. || (tok == OR && n->ntyp == FALSE))
  124. return;
  125. #endif
  126. N = dupnode(n);
  127. if (!can)
  128. { can = N;
  129. return;
  130. }
  131. s = DoDump(N);
  132. if (can->ntyp != tok) /* only one element in list so far */
  133. { ptr = &can;
  134. goto insert;
  135. }
  136. /* there are at least 2 elements in list */
  137. prev = ZN;
  138. for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
  139. { t = DoDump(m->lft);
  140. cmp = strcmp(s->name, t->name);
  141. if (cmp == 0) /* duplicate */
  142. return;
  143. if (cmp < 0)
  144. { if (!prev)
  145. { can = tl_nn(tok, N, can);
  146. return;
  147. } else
  148. { ptr = &(prev->rgt);
  149. goto insert;
  150. } } }
  151. /* new entry goes at the end of the list */
  152. ptr = &(prev->rgt);
  153. insert:
  154. t = DoDump(*ptr);
  155. cmp = strcmp(s->name, t->name);
  156. if (cmp == 0) /* duplicate */
  157. return;
  158. if (cmp < 0)
  159. *ptr = tl_nn(tok, N, *ptr);
  160. else
  161. *ptr = tl_nn(tok, *ptr, N);
  162. }
  163. static void
  164. marknode(int tok, Node *m)
  165. {
  166. if (m->ntyp != tok)
  167. { releasenode(0, m->rgt);
  168. m->rgt = ZN;
  169. }
  170. m->ntyp = -1;
  171. }
  172. Node *
  173. Canonical(Node *n)
  174. { Node *m, *p, *k1, *k2, *prev, *dflt = ZN;
  175. int tok;
  176. if (!n) return n;
  177. tok = n->ntyp;
  178. if (tok != AND && tok != OR)
  179. return n;
  180. can = ZN;
  181. addcan(tok, n);
  182. #if 1
  183. Debug("\nA0: "); Dump(can);
  184. Debug("\nA1: "); Dump(n); Debug("\n");
  185. #endif
  186. releasenode(1, n);
  187. /* mark redundant nodes */
  188. if (tok == AND)
  189. { for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
  190. { k1 = (m->ntyp == AND) ? m->lft : m;
  191. if (k1->ntyp == TRUE)
  192. { marknode(AND, m);
  193. dflt = True;
  194. continue;
  195. }
  196. if (k1->ntyp == FALSE)
  197. { releasenode(1, can);
  198. can = False;
  199. goto out;
  200. } }
  201. for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
  202. for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN)
  203. { if (p == m
  204. || p->ntyp == -1
  205. || m->ntyp == -1)
  206. continue;
  207. k1 = (m->ntyp == AND) ? m->lft : m;
  208. k2 = (p->ntyp == AND) ? p->lft : p;
  209. if (isequal(k1, k2))
  210. { marknode(AND, p);
  211. continue;
  212. }
  213. if (anywhere(OR, k1, k2))
  214. { marknode(AND, p);
  215. continue;
  216. }
  217. if (k2->ntyp == U_OPER
  218. && anywhere(AND, k2->rgt, can))
  219. { marknode(AND, p);
  220. continue;
  221. } /* q && (p U q) = q */
  222. } }
  223. if (tok == OR)
  224. { for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
  225. { k1 = (m->ntyp == OR) ? m->lft : m;
  226. if (k1->ntyp == FALSE)
  227. { marknode(OR, m);
  228. dflt = False;
  229. continue;
  230. }
  231. if (k1->ntyp == TRUE)
  232. { releasenode(1, can);
  233. can = True;
  234. goto out;
  235. } }
  236. for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
  237. for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN)
  238. { if (p == m
  239. || p->ntyp == -1
  240. || m->ntyp == -1)
  241. continue;
  242. k1 = (m->ntyp == OR) ? m->lft : m;
  243. k2 = (p->ntyp == OR) ? p->lft : p;
  244. if (isequal(k1, k2))
  245. { marknode(OR, p);
  246. continue;
  247. }
  248. if (anywhere(AND, k1, k2))
  249. { marknode(OR, p);
  250. continue;
  251. }
  252. if (k2->ntyp == V_OPER
  253. && k2->lft->ntyp == FALSE
  254. && anywhere(AND, k2->rgt, can))
  255. { marknode(OR, p);
  256. continue;
  257. } /* p || (F V p) = p */
  258. } }
  259. for (m = can, prev = ZN; m; ) /* remove marked nodes */
  260. { if (m->ntyp == -1)
  261. { k2 = m->rgt;
  262. releasenode(0, m);
  263. if (!prev)
  264. { m = can = can->rgt;
  265. } else
  266. { m = prev->rgt = k2;
  267. /* if deleted the last node in a chain */
  268. if (!prev->rgt && prev->lft
  269. && (prev->ntyp == AND || prev->ntyp == OR))
  270. { k1 = prev->lft;
  271. prev->ntyp = prev->lft->ntyp;
  272. prev->sym = prev->lft->sym;
  273. prev->rgt = prev->lft->rgt;
  274. prev->lft = prev->lft->lft;
  275. releasenode(0, k1);
  276. }
  277. }
  278. continue;
  279. }
  280. prev = m;
  281. m = m->rgt;
  282. }
  283. out:
  284. #if 1
  285. Debug("A2: "); Dump(can); Debug("\n");
  286. #endif
  287. if (!can)
  288. { if (!dflt)
  289. fatal("cannot happen, Canonical", (char *) 0);
  290. return dflt;
  291. }
  292. return can;
  293. }