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.

653 lines
19 KiB

  1. /***** ltl2ba : buchi.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 GState **init, *gstates;
  33. extern struct rusage tr_debut, tr_fin;
  34. extern struct timeval t_diff;
  35. extern int tl_verbose, tl_stats, tl_simp_diff, tl_simp_fly, tl_simp_scc,
  36. init_size, *final;
  37. extern void put_uform(void);
  38. extern FILE *tl_out;
  39. BState *bstack, *bstates, *bremoved;
  40. BScc *scc_stack;
  41. int accept, bstate_count = 0, btrans_count = 0, rank;
  42. /********************************************************************\
  43. |* Simplification of the generalized Buchi automaton *|
  44. \********************************************************************/
  45. void free_bstate(BState *s) /* frees a state and its transitions */
  46. {
  47. free_btrans(s->trans->nxt, s->trans, 1);
  48. tfree(s);
  49. }
  50. BState *remove_bstate(BState *s, BState *s1) /* removes a state */
  51. {
  52. BState *prv = s->prv;
  53. s->prv->nxt = s->nxt;
  54. s->nxt->prv = s->prv;
  55. free_btrans(s->trans->nxt, s->trans, 0);
  56. s->trans = (BTrans *)0;
  57. s->nxt = bremoved->nxt;
  58. bremoved->nxt = s;
  59. s->prv = s1;
  60. for(s1 = bremoved->nxt; s1 != bremoved; s1 = s1->nxt)
  61. if(s1->prv == s)
  62. s1->prv = s->prv;
  63. return prv;
  64. }
  65. void copy_btrans(BTrans *from, BTrans *to) {
  66. to->to = from->to;
  67. copy_set(from->pos, to->pos, 1);
  68. copy_set(from->neg, to->neg, 1);
  69. }
  70. int simplify_btrans() /* simplifies the transitions */
  71. {
  72. BState *s;
  73. BTrans *t, *t1;
  74. int changed = 0;
  75. if(tl_stats) getrusage(RUSAGE_SELF, &tr_debut);
  76. for (s = bstates->nxt; s != bstates; s = s->nxt)
  77. for (t = s->trans->nxt; t != s->trans;) {
  78. t1 = s->trans->nxt;
  79. copy_btrans(t, s->trans);
  80. while((t == t1) || (t->to != t1->to) ||
  81. !included_set(t1->pos, t->pos, 1) ||
  82. !included_set(t1->neg, t->neg, 1))
  83. t1 = t1->nxt;
  84. if(t1 != s->trans) {
  85. BTrans *free = t->nxt;
  86. t->to = free->to;
  87. copy_set(free->pos, t->pos, 1);
  88. copy_set(free->neg, t->neg, 1);
  89. t->nxt = free->nxt;
  90. if(free == s->trans) s->trans = t;
  91. free_btrans(free, 0, 0);
  92. changed++;
  93. }
  94. else
  95. t = t->nxt;
  96. }
  97. if(tl_stats) {
  98. getrusage(RUSAGE_SELF, &tr_fin);
  99. timeval_subtract (&t_diff, &tr_fin.ru_utime, &tr_debut.ru_utime);
  100. fprintf(tl_out, "\nSimplification of the Buchi automaton - transitions: %i.%06is",
  101. t_diff.tv_sec, t_diff.tv_usec);
  102. fprintf(tl_out, "\n%i transitions removed\n", changed);
  103. }
  104. return changed;
  105. }
  106. int same_btrans(BTrans *s, BTrans *t) /* returns 1 if the transitions are identical */
  107. {
  108. return((s->to == t->to) &&
  109. same_sets(s->pos, t->pos, 1) &&
  110. same_sets(s->neg, t->neg, 1));
  111. }
  112. void remove_btrans(BState *to)
  113. { /* redirects transitions before removing a state from the automaton */
  114. BState *s;
  115. BTrans *t;
  116. int i;
  117. for (s = bstates->nxt; s != bstates; s = s->nxt)
  118. for (t = s->trans->nxt; t != s->trans; t = t->nxt)
  119. if (t->to == to) { /* transition to a state with no transitions */
  120. BTrans *free = t->nxt;
  121. t->to = free->to;
  122. copy_set(free->pos, t->pos, 1);
  123. copy_set(free->neg, t->neg, 1);
  124. t->nxt = free->nxt;
  125. if(free == s->trans) s->trans = t;
  126. free_btrans(free, 0, 0);
  127. }
  128. }
  129. void retarget_all_btrans()
  130. { /* redirects transitions before removing a state from the automaton */
  131. BState *s;
  132. BTrans *t;
  133. for (s = bstates->nxt; s != bstates; s = s->nxt)
  134. for (t = s->trans->nxt; t != s->trans; t = t->nxt)
  135. if (!t->to->trans) { /* t->to has been removed */
  136. t->to = t->to->prv;
  137. if(!t->to) { /* t->to has no transitions */
  138. BTrans *free = t->nxt;
  139. t->to = free->to;
  140. copy_set(free->pos, t->pos, 1);
  141. copy_set(free->neg, t->neg, 1);
  142. t->nxt = free->nxt;
  143. if(free == s->trans) s->trans = t;
  144. free_btrans(free, 0, 0);
  145. }
  146. }
  147. while(bremoved->nxt != bremoved) { /* clean the 'removed' list */
  148. s = bremoved->nxt;
  149. bremoved->nxt = bremoved->nxt->nxt;
  150. tfree(s);
  151. }
  152. }
  153. int all_btrans_match(BState *a, BState *b) /* decides if the states are equivalent */
  154. {
  155. BTrans *s, *t;
  156. if (((a->final == accept) || (b->final == accept)) &&
  157. (a->final + b->final != 2 * accept) &&
  158. a->incoming >=0 && b->incoming >=0)
  159. return 0; /* the states have to be both final or both non final */
  160. for (s = a->trans->nxt; s != a->trans; s = s->nxt) {
  161. /* all transitions from a appear in b */
  162. copy_btrans(s, b->trans);
  163. t = b->trans->nxt;
  164. while(!same_btrans(s, t))
  165. t = t->nxt;
  166. if(t == b->trans) return 0;
  167. }
  168. for (s = b->trans->nxt; s != b->trans; s = s->nxt) {
  169. /* all transitions from b appear in a */
  170. copy_btrans(s, a->trans);
  171. t = a->trans->nxt;
  172. while(!same_btrans(s, t))
  173. t = t->nxt;
  174. if(t == a->trans) return 0;
  175. }
  176. return 1;
  177. }
  178. int simplify_bstates() /* eliminates redundant states */
  179. {
  180. BState *s, *s1;
  181. int changed = 0;
  182. if(tl_stats) getrusage(RUSAGE_SELF, &tr_debut);
  183. for (s = bstates->nxt; s != bstates; s = s->nxt) {
  184. if(s->trans == s->trans->nxt) { /* s has no transitions */
  185. s = remove_bstate(s, (BState *)0);
  186. changed++;
  187. continue;
  188. }
  189. bstates->trans = s->trans;
  190. bstates->final = s->final;
  191. s1 = s->nxt;
  192. while(!all_btrans_match(s, s1))
  193. s1 = s1->nxt;
  194. if(s1 != bstates) { /* s and s1 are equivalent */
  195. if(s1->incoming == -1)
  196. s1->final = s->final; /* get the good final condition */
  197. s = remove_bstate(s, s1);
  198. changed++;
  199. }
  200. }
  201. retarget_all_btrans();
  202. if(tl_stats) {
  203. getrusage(RUSAGE_SELF, &tr_fin);
  204. timeval_subtract (&t_diff, &tr_fin.ru_utime, &tr_debut.ru_utime);
  205. fprintf(tl_out, "\nSimplification of the Buchi automaton - states: %i.%06is",
  206. t_diff.tv_sec, t_diff.tv_usec);
  207. fprintf(tl_out, "\n%i states removed\n", changed);
  208. }
  209. return changed;
  210. }
  211. int bdfs(BState *s) {
  212. BTrans *t;
  213. BScc *c;
  214. BScc *scc = (BScc *)tl_emalloc(sizeof(BScc));
  215. scc->bstate = s;
  216. scc->rank = rank;
  217. scc->theta = rank++;
  218. scc->nxt = scc_stack;
  219. scc_stack = scc;
  220. s->incoming = 1;
  221. for (t = s->trans->nxt; t != s->trans; t = t->nxt) {
  222. if (t->to->incoming == 0) {
  223. int result = bdfs(t->to);
  224. scc->theta = min(scc->theta, result);
  225. }
  226. else {
  227. for(c = scc_stack->nxt; c != 0; c = c->nxt)
  228. if(c->bstate == t->to) {
  229. scc->theta = min(scc->theta, c->rank);
  230. break;
  231. }
  232. }
  233. }
  234. if(scc->rank == scc->theta) {
  235. if(scc_stack == scc) { /* s is alone in a scc */
  236. s->incoming = -1;
  237. for (t = s->trans->nxt; t != s->trans; t = t->nxt)
  238. if (t->to == s)
  239. s->incoming = 1;
  240. }
  241. scc_stack = scc->nxt;
  242. }
  243. return scc->theta;
  244. }
  245. void simplify_bscc() {
  246. BState *s;
  247. rank = 1;
  248. scc_stack = 0;
  249. if(bstates == bstates->nxt) return;
  250. for(s = bstates->nxt; s != bstates; s = s->nxt)
  251. s->incoming = 0; /* state color = white */
  252. bdfs(bstates->prv);
  253. for(s = bstates->nxt; s != bstates; s = s->nxt)
  254. if(s->incoming == 0)
  255. remove_bstate(s, 0);
  256. }
  257. /********************************************************************\
  258. |* Generation of the Buchi automaton *|
  259. \********************************************************************/
  260. BState *find_bstate(GState **state, int final, BState *s)
  261. { /* finds the corresponding state, or creates it */
  262. if((s->gstate == *state) && (s->final == final)) return s; /* same state */
  263. s = bstack->nxt; /* in the stack */
  264. bstack->gstate = *state;
  265. bstack->final = final;
  266. while(!(s->gstate == *state) || !(s->final == final))
  267. s = s->nxt;
  268. if(s != bstack) return s;
  269. s = bstates->nxt; /* in the solved states */
  270. bstates->gstate = *state;
  271. bstates->final = final;
  272. while(!(s->gstate == *state) || !(s->final == final))
  273. s = s->nxt;
  274. if(s != bstates) return s;
  275. s = bremoved->nxt; /* in the removed states */
  276. bremoved->gstate = *state;
  277. bremoved->final = final;
  278. while(!(s->gstate == *state) || !(s->final == final))
  279. s = s->nxt;
  280. if(s != bremoved) return s;
  281. s = (BState *)tl_emalloc(sizeof(BState)); /* creates a new state */
  282. s->gstate = *state;
  283. s->id = (*state)->id;
  284. s->incoming = 0;
  285. s->final = final;
  286. s->trans = emalloc_btrans(); /* sentinel */
  287. s->trans->nxt = s->trans;
  288. s->nxt = bstack->nxt;
  289. bstack->nxt = s;
  290. return s;
  291. }
  292. int next_final(int *set, int fin) /* computes the 'final' value */
  293. {
  294. if((fin != accept) && in_set(set, final[fin + 1]))
  295. return next_final(set, fin + 1);
  296. return fin;
  297. }
  298. void make_btrans(BState *s) /* creates all the transitions from a state */
  299. {
  300. int state_trans = 0;
  301. GTrans *t;
  302. BTrans *t1;
  303. BState *s1;
  304. if(s->gstate->trans)
  305. for(t = s->gstate->trans->nxt; t != s->gstate->trans; t = t->nxt) {
  306. int fin = next_final(t->final, (s->final == accept) ? 0 : s->final);
  307. BState *to = find_bstate(&t->to, fin, s);
  308. for(t1 = s->trans->nxt; t1 != s->trans;) {
  309. if(tl_simp_fly &&
  310. (to == t1->to) &&
  311. included_set(t->pos, t1->pos, 1) &&
  312. included_set(t->neg, t1->neg, 1)) { /* t1 is redondant */
  313. BTrans *free = t1->nxt;
  314. t1->to->incoming--;
  315. t1->to = free->to;
  316. copy_set(free->pos, t1->pos, 1);
  317. copy_set(free->neg, t1->neg, 1);
  318. t1->nxt = free->nxt;
  319. if(free == s->trans) s->trans = t1;
  320. free_btrans(free, 0, 0);
  321. state_trans--;
  322. }
  323. else if(tl_simp_fly &&
  324. (t1->to == to ) &&
  325. included_set(t1->pos, t->pos, 1) &&
  326. included_set(t1->neg, t->neg, 1)) /* t is redondant */
  327. break;
  328. else
  329. t1 = t1->nxt;
  330. }
  331. if(t1 == s->trans) {
  332. BTrans *trans = emalloc_btrans();
  333. trans->to = to;
  334. trans->to->incoming++;
  335. copy_set(t->pos, trans->pos, 1);
  336. copy_set(t->neg, trans->neg, 1);
  337. trans->nxt = s->trans->nxt;
  338. s->trans->nxt = trans;
  339. state_trans++;
  340. }
  341. }
  342. if(tl_simp_fly) {
  343. if(s->trans == s->trans->nxt) { /* s has no transitions */
  344. free_btrans(s->trans->nxt, s->trans, 1);
  345. s->trans = (BTrans *)0;
  346. s->prv = (BState *)0;
  347. s->nxt = bremoved->nxt;
  348. bremoved->nxt = s;
  349. for(s1 = bremoved->nxt; s1 != bremoved; s1 = s1->nxt)
  350. if(s1->prv == s)
  351. s1->prv = (BState *)0;
  352. return;
  353. }
  354. bstates->trans = s->trans;
  355. bstates->final = s->final;
  356. s1 = bstates->nxt;
  357. while(!all_btrans_match(s, s1))
  358. s1 = s1->nxt;
  359. if(s1 != bstates) { /* s and s1 are equivalent */
  360. free_btrans(s->trans->nxt, s->trans, 1);
  361. s->trans = (BTrans *)0;
  362. s->prv = s1;
  363. s->nxt = bremoved->nxt;
  364. bremoved->nxt = s;
  365. for(s1 = bremoved->nxt; s1 != bremoved; s1 = s1->nxt)
  366. if(s1->prv == s)
  367. s1->prv = s->prv;
  368. return;
  369. }
  370. }
  371. s->nxt = bstates->nxt; /* adds the current state to 'bstates' */
  372. s->prv = bstates;
  373. s->nxt->prv = s;
  374. bstates->nxt = s;
  375. btrans_count += state_trans;
  376. bstate_count++;
  377. }
  378. /********************************************************************\
  379. |* Display of the Buchi automaton *|
  380. \********************************************************************/
  381. void print_buchi(BState *s) /* dumps the Buchi automaton */
  382. {
  383. BTrans *t;
  384. if(s == bstates) return;
  385. print_buchi(s->nxt); /* begins with the last state */
  386. fprintf(tl_out, "state ");
  387. if(s->id == -1)
  388. fprintf(tl_out, "init");
  389. else {
  390. if(s->final == accept)
  391. fprintf(tl_out, "accept");
  392. else
  393. fprintf(tl_out, "T%i", s->final);
  394. fprintf(tl_out, "_%i", s->id);
  395. }
  396. fprintf(tl_out, "\n");
  397. for(t = s->trans->nxt; t != s->trans; t = t->nxt) {
  398. if (empty_set(t->pos, 1) && empty_set(t->neg, 1))
  399. fprintf(tl_out, "1");
  400. print_set(t->pos, 1);
  401. if (!empty_set(t->pos, 1) && !empty_set(t->neg, 1)) fprintf(tl_out, " & ");
  402. print_set(t->neg, 2);
  403. fprintf(tl_out, " -> ");
  404. if(t->to->id == -1)
  405. fprintf(tl_out, "init\n");
  406. else {
  407. if(t->to->final == accept)
  408. fprintf(tl_out, "accept");
  409. else
  410. fprintf(tl_out, "T%i", t->to->final);
  411. fprintf(tl_out, "_%i\n", t->to->id);
  412. }
  413. }
  414. }
  415. void print_spin_buchi() {
  416. BTrans *t;
  417. BState *s;
  418. int accept_all = 0, init_count = 0;
  419. if(bstates->nxt == bstates) { /* empty automaton */
  420. fprintf(tl_out, "never { /* ");
  421. put_uform();
  422. fprintf(tl_out, " */\n");
  423. fprintf(tl_out, "T0_init:\n");
  424. fprintf(tl_out, "\tfalse;\n");
  425. fprintf(tl_out, "}\n");
  426. return;
  427. }
  428. if(bstates->nxt->nxt == bstates && bstates->nxt->id == 0) { /* true */
  429. fprintf(tl_out, "never { /* ");
  430. put_uform();
  431. fprintf(tl_out, " */\n");
  432. fprintf(tl_out, "accept_init:\n");
  433. fprintf(tl_out, "\tif\n");
  434. fprintf(tl_out, "\t:: (1) -> goto accept_init\n");
  435. fprintf(tl_out, "\tfi;\n");
  436. fprintf(tl_out, "}\n");
  437. return;
  438. }
  439. fprintf(tl_out, "never { /* ");
  440. put_uform();
  441. fprintf(tl_out, " */\n");
  442. for(s = bstates->prv; s != bstates; s = s->prv) {
  443. if(s->id == 0) { /* accept_all at the end */
  444. accept_all = 1;
  445. continue;
  446. }
  447. if(s->final == accept)
  448. fprintf(tl_out, "accept_");
  449. else fprintf(tl_out, "T%i_", s->final);
  450. if(s->id == -1)
  451. fprintf(tl_out, "init:\n");
  452. else fprintf(tl_out, "S%i:\n", s->id);
  453. if(s->trans->nxt == s->trans) {
  454. fprintf(tl_out, "\tfalse;\n");
  455. continue;
  456. }
  457. fprintf(tl_out, "\tif\n");
  458. for(t = s->trans->nxt; t != s->trans; t = t->nxt) {
  459. BTrans *t1;
  460. fprintf(tl_out, "\t:: (");
  461. spin_print_set(t->pos, t->neg);
  462. for(t1 = t; t1->nxt != s->trans; )
  463. if (t1->nxt->to->id == t->to->id &&
  464. t1->nxt->to->final == t->to->final) {
  465. fprintf(tl_out, ") || (");
  466. spin_print_set(t1->nxt->pos, t1->nxt->neg);
  467. t1->nxt = t1->nxt->nxt;
  468. }
  469. else t1 = t1->nxt;
  470. fprintf(tl_out, ") -> goto ");
  471. if(t->to->final == accept)
  472. fprintf(tl_out, "accept_");
  473. else fprintf(tl_out, "T%i_", t->to->final);
  474. if(t->to->id == 0)
  475. fprintf(tl_out, "all\n");
  476. else if(t->to->id == -1)
  477. fprintf(tl_out, "init\n");
  478. else fprintf(tl_out, "S%i\n", t->to->id);
  479. }
  480. fprintf(tl_out, "\tfi;\n");
  481. }
  482. if(accept_all) {
  483. fprintf(tl_out, "accept_all:\n");
  484. fprintf(tl_out, "\tskip\n");
  485. }
  486. fprintf(tl_out, "}\n");
  487. }
  488. /********************************************************************\
  489. |* Main method *|
  490. \********************************************************************/
  491. void mk_buchi()
  492. {/* generates a Buchi automaton from the generalized Buchi automaton */
  493. int i;
  494. BState *s = (BState *)tl_emalloc(sizeof(BState));
  495. GTrans *t;
  496. BTrans *t1;
  497. accept = final[0] - 1;
  498. if(tl_stats) getrusage(RUSAGE_SELF, &tr_debut);
  499. bstack = (BState *)tl_emalloc(sizeof(BState)); /* sentinel */
  500. bstack->nxt = bstack;
  501. bremoved = (BState *)tl_emalloc(sizeof(BState)); /* sentinel */
  502. bremoved->nxt = bremoved;
  503. bstates = (BState *)tl_emalloc(sizeof(BState)); /* sentinel */
  504. bstates->nxt = s;
  505. bstates->prv = s;
  506. s->nxt = bstates; /* creates (unique) inital state */
  507. s->prv = bstates;
  508. s->id = -1;
  509. s->incoming = 1;
  510. s->final = 0;
  511. s->gstate = 0;
  512. s->trans = emalloc_btrans(); /* sentinel */
  513. s->trans->nxt = s->trans;
  514. for(i = 0; i < init_size; i++)
  515. if(init[i])
  516. for(t = init[i]->trans->nxt; t != init[i]->trans; t = t->nxt) {
  517. int fin = next_final(t->final, 0);
  518. BState *to = find_bstate(&t->to, fin, s);
  519. for(t1 = s->trans->nxt; t1 != s->trans;) {
  520. if(tl_simp_fly &&
  521. (to == t1->to) &&
  522. included_set(t->pos, t1->pos, 1) &&
  523. included_set(t->neg, t1->neg, 1)) { /* t1 is redondant */
  524. BTrans *free = t1->nxt;
  525. t1->to->incoming--;
  526. t1->to = free->to;
  527. copy_set(free->pos, t1->pos, 1);
  528. copy_set(free->neg, t1->neg, 1);
  529. t1->nxt = free->nxt;
  530. if(free == s->trans) s->trans = t1;
  531. free_btrans(free, 0, 0);
  532. }
  533. else if(tl_simp_fly &&
  534. (t1->to == to ) &&
  535. included_set(t1->pos, t->pos, 1) &&
  536. included_set(t1->neg, t->neg, 1)) /* t is redondant */
  537. break;
  538. else
  539. t1 = t1->nxt;
  540. }
  541. if(t1 == s->trans) {
  542. BTrans *trans = emalloc_btrans();
  543. trans->to = to;
  544. trans->to->incoming++;
  545. copy_set(t->pos, trans->pos, 1);
  546. copy_set(t->neg, trans->neg, 1);
  547. trans->nxt = s->trans->nxt;
  548. s->trans->nxt = trans;
  549. }
  550. }
  551. while(bstack->nxt != bstack) { /* solves all states in the stack until it is empty */
  552. s = bstack->nxt;
  553. bstack->nxt = bstack->nxt->nxt;
  554. if(!s->incoming) {
  555. free_bstate(s);
  556. continue;
  557. }
  558. make_btrans(s);
  559. }
  560. retarget_all_btrans();
  561. if(tl_stats) {
  562. getrusage(RUSAGE_SELF, &tr_fin);
  563. timeval_subtract (&t_diff, &tr_fin.ru_utime, &tr_debut.ru_utime);
  564. fprintf(tl_out, "\nBuilding the Buchi automaton : %i.%06is",
  565. t_diff.tv_sec, t_diff.tv_usec);
  566. fprintf(tl_out, "\n%i states, %i transitions\n", bstate_count, btrans_count);
  567. }
  568. if(tl_verbose) {
  569. fprintf(tl_out, "\nBuchi automaton before simplification\n");
  570. print_buchi(bstates->nxt);
  571. if(bstates == bstates->nxt)
  572. fprintf(tl_out, "empty automaton, refuses all words\n");
  573. }
  574. if(tl_simp_diff) {
  575. simplify_btrans();
  576. if(tl_simp_scc) simplify_bscc();
  577. while(simplify_bstates()) { /* simplifies as much as possible */
  578. simplify_btrans();
  579. if(tl_simp_scc) simplify_bscc();
  580. }
  581. if(tl_verbose) {
  582. fprintf(tl_out, "\nBuchi automaton after simplification\n");
  583. print_buchi(bstates->nxt);
  584. if(bstates == bstates->nxt)
  585. fprintf(tl_out, "empty automaton, refuses all words\n");
  586. fprintf(tl_out, "\n");
  587. }
  588. }
  589. print_spin_buchi();
  590. }