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.

443 lines
12 KiB

  1. /***** ltl2ba : alternating.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. #include "ltl2ba.h"
  29. /********************************************************************\
  30. |* Structures and shared variables *|
  31. \********************************************************************/
  32. extern FILE *tl_out;
  33. extern int tl_verbose, tl_stats, tl_simp_diff;
  34. Node **label;
  35. char **sym_table;
  36. ATrans **transition;
  37. struct rusage tr_debut, tr_fin;
  38. struct timeval t_diff;
  39. int *final_set, node_id = 1, sym_id = 0, node_size, sym_size;
  40. int astate_count = 0, atrans_count = 0;
  41. ATrans *build_alternating(Node *p);
  42. /********************************************************************\
  43. |* Generation of the alternating automaton *|
  44. \********************************************************************/
  45. int calculate_node_size(Node *p) /* returns the number of temporal nodes */
  46. {
  47. switch(p->ntyp) {
  48. case AND:
  49. case OR:
  50. case U_OPER:
  51. case V_OPER:
  52. return(calculate_node_size(p->lft) + calculate_node_size(p->rgt) + 1);
  53. #ifdef NXT
  54. case NEXT:
  55. return(calculate_node_size(p->lft) + 1);
  56. #endif
  57. default:
  58. return 1;
  59. break;
  60. }
  61. }
  62. int calculate_sym_size(Node *p) /* returns the number of predicates */
  63. {
  64. switch(p->ntyp) {
  65. case AND:
  66. case OR:
  67. case U_OPER:
  68. case V_OPER:
  69. return(calculate_sym_size(p->lft) + calculate_sym_size(p->rgt));
  70. #ifdef NXT
  71. case NEXT:
  72. return(calculate_sym_size(p->lft));
  73. #endif
  74. case NOT:
  75. case PREDICATE:
  76. return 1;
  77. default:
  78. return 0;
  79. }
  80. }
  81. ATrans *dup_trans(ATrans *trans) /* returns the copy of a transition */
  82. {
  83. ATrans *result;
  84. if(!trans) return trans;
  85. result = emalloc_atrans();
  86. copy_set(trans->to, result->to, 0);
  87. copy_set(trans->pos, result->pos, 1);
  88. copy_set(trans->neg, result->neg, 1);
  89. return result;
  90. }
  91. void do_merge_trans(ATrans **result, ATrans *trans1, ATrans *trans2)
  92. { /* merges two transitions */
  93. if(!trans1 || !trans2) {
  94. free_atrans(*result, 0);
  95. *result = (ATrans *)0;
  96. return;
  97. }
  98. if(!*result)
  99. *result = emalloc_atrans();
  100. do_merge_sets((*result)->to, trans1->to, trans2->to, 0);
  101. do_merge_sets((*result)->pos, trans1->pos, trans2->pos, 1);
  102. do_merge_sets((*result)->neg, trans1->neg, trans2->neg, 1);
  103. if(!empty_intersect_sets((*result)->pos, (*result)->neg, 1)) {
  104. free_atrans(*result, 0);
  105. *result = (ATrans *)0;
  106. }
  107. }
  108. ATrans *merge_trans(ATrans *trans1, ATrans *trans2) /* merges two transitions */
  109. {
  110. ATrans *result = emalloc_atrans();
  111. do_merge_trans(&result, trans1, trans2);
  112. return result;
  113. }
  114. int already_done(Node *p) /* finds the id of the node, if already explored */
  115. {
  116. int i;
  117. for(i = 1; i<node_id; i++)
  118. if (isequal(p, label[i]))
  119. return i;
  120. return -1;
  121. }
  122. int get_sym_id(char *s) /* finds the id of a predicate, or attributes one */
  123. {
  124. int i;
  125. for(i=0; i<sym_id; i++)
  126. if (!strcmp(s, sym_table[i]))
  127. return i;
  128. sym_table[sym_id] = s;
  129. return sym_id++;
  130. }
  131. ATrans *boolean(Node *p) /* computes the transitions to boolean nodes -> next & init */
  132. {
  133. ATrans *t1, *t2, *lft, *rgt, *result = (ATrans *)0;
  134. int id;
  135. switch(p->ntyp) {
  136. case TRUE:
  137. result = emalloc_atrans();
  138. clear_set(result->to, 0);
  139. clear_set(result->pos, 1);
  140. clear_set(result->neg, 1);
  141. case FALSE:
  142. break;
  143. case AND:
  144. lft = boolean(p->lft);
  145. rgt = boolean(p->rgt);
  146. for(t1 = lft; t1; t1 = t1->nxt) {
  147. for(t2 = rgt; t2; t2 = t2->nxt) {
  148. ATrans *tmp = merge_trans(t1, t2);
  149. if(tmp) {
  150. tmp->nxt = result;
  151. result = tmp;
  152. }
  153. }
  154. }
  155. free_atrans(lft, 1);
  156. free_atrans(rgt, 1);
  157. break;
  158. case OR:
  159. lft = boolean(p->lft);
  160. for(t1 = lft; t1; t1 = t1->nxt) {
  161. ATrans *tmp = dup_trans(t1);
  162. tmp->nxt = result;
  163. result = tmp;
  164. }
  165. free_atrans(lft, 1);
  166. rgt = boolean(p->rgt);
  167. for(t1 = rgt; t1; t1 = t1->nxt) {
  168. ATrans *tmp = dup_trans(t1);
  169. tmp->nxt = result;
  170. result = tmp;
  171. }
  172. free_atrans(rgt, 1);
  173. break;
  174. default:
  175. build_alternating(p);
  176. result = emalloc_atrans();
  177. clear_set(result->to, 0);
  178. clear_set(result->pos, 1);
  179. clear_set(result->neg, 1);
  180. add_set(result->to, already_done(p));
  181. }
  182. return result;
  183. }
  184. ATrans *build_alternating(Node *p) /* builds an alternating automaton for p */
  185. {
  186. ATrans *t1, *t2, *t = (ATrans *)0;
  187. int node = already_done(p);
  188. if(node >= 0) return transition[node];
  189. switch (p->ntyp) {
  190. case TRUE:
  191. t = emalloc_atrans();
  192. clear_set(t->to, 0);
  193. clear_set(t->pos, 1);
  194. clear_set(t->neg, 1);
  195. case FALSE:
  196. break;
  197. case PREDICATE:
  198. t = emalloc_atrans();
  199. clear_set(t->to, 0);
  200. clear_set(t->pos, 1);
  201. clear_set(t->neg, 1);
  202. add_set(t->pos, get_sym_id(p->sym->name));
  203. break;
  204. case NOT:
  205. t = emalloc_atrans();
  206. clear_set(t->to, 0);
  207. clear_set(t->pos, 1);
  208. clear_set(t->neg, 1);
  209. add_set(t->neg, get_sym_id(p->lft->sym->name));
  210. break;
  211. #ifdef NXT
  212. case NEXT:
  213. t = boolean(p->lft);
  214. break;
  215. #endif
  216. case U_OPER: /* p U q <-> q || (p && X (p U q)) */
  217. for(t2 = build_alternating(p->rgt); t2; t2 = t2->nxt) {
  218. ATrans *tmp = dup_trans(t2); /* q */
  219. tmp->nxt = t;
  220. t = tmp;
  221. }
  222. for(t1 = build_alternating(p->lft); t1; t1 = t1->nxt) {
  223. ATrans *tmp = dup_trans(t1); /* p */
  224. add_set(tmp->to, node_id); /* X (p U q) */
  225. tmp->nxt = t;
  226. t = tmp;
  227. }
  228. add_set(final_set, node_id);
  229. break;
  230. case V_OPER: /* p V q <-> (p && q) || (p && X (p V q)) */
  231. for(t1 = build_alternating(p->rgt); t1; t1 = t1->nxt) {
  232. ATrans *tmp;
  233. for(t2 = build_alternating(p->lft); t2; t2 = t2->nxt) {
  234. tmp = merge_trans(t1, t2); /* p && q */
  235. if(tmp) {
  236. tmp->nxt = t;
  237. t = tmp;
  238. }
  239. }
  240. tmp = dup_trans(t1); /* p */
  241. add_set(tmp->to, node_id); /* X (p V q) */
  242. tmp->nxt = t;
  243. t = tmp;
  244. }
  245. break;
  246. case AND:
  247. t = (ATrans *)0;
  248. for(t1 = build_alternating(p->lft); t1; t1 = t1->nxt) {
  249. for(t2 = build_alternating(p->rgt); t2; t2 = t2->nxt) {
  250. ATrans *tmp = merge_trans(t1, t2);
  251. if(tmp) {
  252. tmp->nxt = t;
  253. t = tmp;
  254. }
  255. }
  256. }
  257. break;
  258. case OR:
  259. t = (ATrans *)0;
  260. for(t1 = build_alternating(p->lft); t1; t1 = t1->nxt) {
  261. ATrans *tmp = dup_trans(t1);
  262. tmp->nxt = t;
  263. t = tmp;
  264. }
  265. for(t1 = build_alternating(p->rgt); t1; t1 = t1->nxt) {
  266. ATrans *tmp = dup_trans(t1);
  267. tmp->nxt = t;
  268. t = tmp;
  269. }
  270. break;
  271. default:
  272. break;
  273. }
  274. transition[node_id] = t;
  275. label[node_id++] = p;
  276. return(t);
  277. }
  278. /********************************************************************\
  279. |* Simplification of the alternating automaton *|
  280. \********************************************************************/
  281. void simplify_atrans(ATrans **trans) /* simplifies the transitions */
  282. {
  283. ATrans *t, *father = (ATrans *)0;
  284. for(t = *trans; t;) {
  285. ATrans *t1;
  286. for(t1 = *trans; t1; t1 = t1->nxt) {
  287. if((t1 != t) &&
  288. included_set(t1->to, t->to, 0) &&
  289. included_set(t1->pos, t->pos, 1) &&
  290. included_set(t1->neg, t->neg, 1))
  291. break;
  292. }
  293. if(t1) {
  294. if (father)
  295. father->nxt = t->nxt;
  296. else
  297. *trans = t->nxt;
  298. free_atrans(t, 0);
  299. if (father)
  300. t = father->nxt;
  301. else
  302. t = *trans;
  303. continue;
  304. }
  305. atrans_count++;
  306. father = t;
  307. t = t->nxt;
  308. }
  309. }
  310. void simplify_astates() /* simplifies the alternating automaton */
  311. {
  312. ATrans *t;
  313. int i, *acc = make_set(-1, 0); /* no state is accessible initially */
  314. for(t = transition[0]; t; t = t->nxt, i = 0)
  315. merge_sets(acc, t->to, 0); /* all initial states are accessible */
  316. for(i = node_id - 1; i > 0; i--) {
  317. if (!in_set(acc, i)) { /* frees unaccessible states */
  318. label[i] = ZN;
  319. free_atrans(transition[i], 1);
  320. transition[i] = (ATrans *)0;
  321. continue;
  322. }
  323. astate_count++;
  324. simplify_atrans(&transition[i]);
  325. for(t = transition[i]; t; t = t->nxt)
  326. merge_sets(acc, t->to, 0);
  327. }
  328. tfree(acc);
  329. }
  330. /********************************************************************\
  331. |* Display of the alternating automaton *|
  332. \********************************************************************/
  333. void print_alternating() /* dumps the alternating automaton */
  334. {
  335. int i;
  336. ATrans *t;
  337. fprintf(tl_out, "init :\n");
  338. for(t = transition[0]; t; t = t->nxt) {
  339. print_set(t->to, 0);
  340. fprintf(tl_out, "\n");
  341. }
  342. for(i = node_id - 1; i > 0; i--) {
  343. if(!label[i])
  344. continue;
  345. fprintf(tl_out, "state %i : ", i);
  346. dump(label[i]);
  347. fprintf(tl_out, "\n");
  348. for(t = transition[i]; t; t = t->nxt) {
  349. if (empty_set(t->pos, 1) && empty_set(t->neg, 1))
  350. fprintf(tl_out, "1");
  351. print_set(t->pos, 1);
  352. if (!empty_set(t->pos,1) && !empty_set(t->neg,1)) fprintf(tl_out, " & ");
  353. print_set(t->neg, 2);
  354. fprintf(tl_out, " -> ");
  355. print_set(t->to, 0);
  356. fprintf(tl_out, "\n");
  357. }
  358. }
  359. }
  360. /********************************************************************\
  361. |* Main method *|
  362. \********************************************************************/
  363. void mk_alternating(Node *p) /* generates an alternating automaton for p */
  364. {
  365. if(tl_stats) getrusage(RUSAGE_SELF, &tr_debut);
  366. node_size = calculate_node_size(p) + 1; /* number of states in the automaton */
  367. label = (Node **) tl_emalloc(node_size * sizeof(Node *));
  368. transition = (ATrans **) tl_emalloc(node_size * sizeof(ATrans *));
  369. node_size = node_size / (8 * sizeof(int)) + 1;
  370. sym_size = calculate_sym_size(p); /* number of predicates */
  371. if(sym_size) sym_table = (char **) tl_emalloc(sym_size * sizeof(char *));
  372. sym_size = sym_size / (8 * sizeof(int)) + 1;
  373. final_set = make_set(-1, 0);
  374. transition[0] = boolean(p); /* generates the alternating automaton */
  375. if(tl_verbose) {
  376. fprintf(tl_out, "\nAlternating automaton before simplification\n");
  377. print_alternating();
  378. }
  379. if(tl_simp_diff) {
  380. simplify_astates(); /* keeps only accessible states */
  381. if(tl_verbose) {
  382. fprintf(tl_out, "\nAlternating automaton after simplification\n");
  383. print_alternating();
  384. }
  385. }
  386. if(tl_stats) {
  387. getrusage(RUSAGE_SELF, &tr_fin);
  388. timeval_subtract (&t_diff, &tr_fin.ru_utime, &tr_debut.ru_utime);
  389. fprintf(tl_out, "\nBuilding and simplification of the alternating automaton: %i.%06is",
  390. t_diff.tv_sec, t_diff.tv_usec);
  391. fprintf(tl_out, "\n%i states, %i transitions\n", astate_count, atrans_count);
  392. }
  393. releasenode(1, p);
  394. tfree(label);
  395. }