source: vis_dev/vis-2.3/src/ctlp/ctlpUtil.c @ 106

Last change on this file since 106 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 146.6 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [ctlpUtil.c]
4
5  PackageName [ctlp]
6
7  Synopsis    [Routines for manipulating CTL formulas.]
8
9  Description [This file contains routines for accessing the fields of the CTL
10  formula data structure, for printing CTL formulas, for reading CTL formulas
11  from a file, and for converting formulas to the existential form.]
12
13  Remarks [There are two types of conversion routines.  One set, for
14  mc and amc, converts a formula to existential normal form, i.e. the
15  AX, AU and AG operators are converted.  The other set, used in imc,
16  converts to simple existential form, a form consisting only of
17  E-operators and the boolean operators AND and NOT.
18
19  Simple existential form is incompatible with the mc debug routines,
20  because these depend on the specific form of the converted formula
21  to decide what the original formula was.
22
23  In the long run, the existential form should probably go, and the
24  debug routines should be adapted.  The only drawback of simple
25  existential form is that the XOR gets expanded into three nontrivial
26  operations, so maybe XOR (or IFF) should be retained. (RB.)]
27
28
29  Author      [Gary York, Ramin Hojati, Tom Shiple, Adnan Aziz, Yuji Kukimoto,
30               Jae-Young Jang, In-Ho Moon]
31
32  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
33  All rights reserved.
34
35  Permission is hereby granted, without written agreement and without license
36  or royalty fees, to use, copy, modify, and distribute this software and its
37  documentation for any purpose, provided that the above copyright notice and
38  the following two paragraphs appear in all copies of this software.
39
40  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
41  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
42  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
43  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
45  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
46  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
47  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
48  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
49  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
50
51******************************************************************************/
52
53#include "ctlpInt.h"
54#include "errno.h"
55
56static char rcsid[] UNUSED = "$Id: ctlpUtil.c,v 1.71 2009/04/11 18:25:53 fabio Exp $";
57
58
59/*---------------------------------------------------------------------------*/
60/* Variable declarations                                                     */
61/*---------------------------------------------------------------------------*/
62
63/**Variable********************************************************************
64
65  Synopsis    [Array of CTL formulas (Ctlp_Formula_t) read from a file.]
66
67  SeeAlso     [Ctlp_FormulaArrayFree]
68
69******************************************************************************/
70static array_t *globalFormulaArray;
71static int      changeBracket = 1;
72
73/* see ctlpInt.h for documentation */
74int CtlpGlobalError;
75Ctlp_Formula_t *CtlpGlobalFormula;
76st_table *CtlpMacroTable;
77
78/*---------------------------------------------------------------------------*/
79/* Macro declarations                                                        */
80/*---------------------------------------------------------------------------*/
81
82
83/**AutomaticStart*************************************************************/
84
85/*---------------------------------------------------------------------------*/
86/* Static function prototypes                                                */
87/*---------------------------------------------------------------------------*/
88
89static Ctlp_Formula_t * FormulaCreateWithType(Ctlp_FormulaType type);
90static int FormulaCompare(const char *key1, const char *key2);
91static int FormulaHash(char *key, int modulus);
92static Ctlp_Formula_t * FormulaHashIntoUniqueTable(Ctlp_Formula_t *formula, st_table *uniqueTable);
93static Ctlp_Formula_t * FormulaConvertToExistentialDAG(Ctlp_Formula_t *formula);
94static void FormulaConvertToForward(Ctlp_Formula_t *formula, int compareValue);
95static void FormulaInsertForwardCompareNodes(Ctlp_Formula_t *formula, Ctlp_Formula_t *parent, int compareValue);
96static int FormulaGetCompareValue(Ctlp_Formula_t *formula);
97static int FormulaIsConvertible(Ctlp_Formula_t *formula);
98static Ctlp_Formula_t * ReplaceSimpleFormula(Ctlp_Formula_t *formula);
99
100/**AutomaticEnd***************************************************************/
101
102
103/*---------------------------------------------------------------------------*/
104/* Definition of exported functions                                          */
105/*---------------------------------------------------------------------------*/
106
107/**Function********************************************************************
108
109  Synopsis    [Parses a file containing a set of CTL formulas.]
110
111  Description [Parses a file containing a set of semicolon-ending CTL
112  formulas, and returns an array of Ctlp_Formula_t representing those
113  formulas.  If an error is detected while parsing the file, the routine frees
114  any allocated memory and returns NULL.]
115
116  SideEffects [Manipulates the global variables globalFormulaArray,
117  CtlpGlobalError and CtlpGlobalFormula.]
118
119  SeeAlso     [Ctlp_FormulaArrayFree Ctlp_FormulaPrint]
120
121******************************************************************************/
122array_t *
123Ctlp_FileParseFormulaArray(
124  FILE * fp)
125{
126  st_generator *stGen;
127  char *name;
128  Ctlp_Formula_t *formula;
129  char *flagValue;
130  /*
131   * Initialize the global variables.
132   */
133  globalFormulaArray = array_alloc(Ctlp_Formula_t *, 0);
134  CtlpGlobalError = 0;
135  CtlpGlobalFormula = NIL(Ctlp_Formula_t);
136  CtlpMacroTable = st_init_table(strcmp,st_strhash);
137  CtlpFileSetup(fp);
138  /*
139   * Check if changing "[] -> <>" is disabled.
140   */
141  flagValue = Cmd_FlagReadByName("ctl_change_bracket");
142  if (flagValue != NIL(char)) {
143    if (strcmp(flagValue, "yes") == 0)
144      changeBracket = 1;
145    else if (strcmp(flagValue, "no") == 0)
146      changeBracket = 0;
147    else {
148      fprintf(vis_stderr,
149        "** ctl error : invalid value %s for ctl_change_bracket[yes/no]. ***\n",
150        flagValue);
151    }
152  }
153
154  (void)CtlpYyparse();
155  st_foreach_item(CtlpMacroTable,stGen,&name,&formula){
156     FREE(name);
157     CtlpFormulaFree(formula);
158  }
159  st_free_table(CtlpMacroTable);
160
161  /*
162   * Clean up if there was an error, otherwise return the array.
163   */
164  if (CtlpGlobalError){
165    Ctlp_FormulaArrayFree(globalFormulaArray);
166    return NIL(array_t);
167  }
168  else {
169    return globalFormulaArray;
170  }
171}
172
173/**Function********************************************************************
174
175  Synopsis    [Returns formula as a character string.]
176
177  Description [Returns formula as a character string. All subformulas are
178  delimited by parenthesis. The syntax used is the same as used by the CTL
179  parser.  Does nothing if passed a NULL formula.]
180
181  SideEffects []
182
183******************************************************************************/
184char *
185Ctlp_FormulaConvertToString(
186  Ctlp_Formula_t * formula)
187{
188  char *s1        = NIL(char);
189  char *s2        = NIL(char);
190  char *tmpString = NIL(char);
191  char *result;
192
193
194  if (formula == NIL(Ctlp_Formula_t)) {
195    return NIL(char);
196  }
197
198  /* The formula is a leaf. */
199  if (formula->type == Ctlp_ID_c){
200    return util_strcat3((char *)(formula->left), "=",(char *)(formula->right));
201  }
202
203  /* If the formula is a non-leaf, the function is called recursively */
204  s1 = Ctlp_FormulaConvertToString(formula->left);
205  s2 = Ctlp_FormulaConvertToString(formula->right);
206
207  switch(formula->type) {
208    /*
209     * The cases are listed in rough order of their expected frequency.
210     */
211    case Ctlp_OR_c:
212      tmpString = util_strcat3(s1, " + ",s2);
213      result    = util_strcat3("(", tmpString, ")");
214      break;
215    case Ctlp_AND_c:
216      tmpString = util_strcat3(s1, " * ", s2);
217      result    = util_strcat3("(", tmpString, ")");
218      break;
219    case Ctlp_THEN_c:
220      tmpString = util_strcat3(s1, " -> ", s2);
221      result    = util_strcat3("(", tmpString, ")");
222      break;
223    case Ctlp_XOR_c:
224      tmpString = util_strcat3(s1, " ^ ", s2);
225      result    = util_strcat3("(", tmpString, ")");
226      break;
227    case Ctlp_EQ_c:
228      tmpString = util_strcat3(s1, " <-> ", s2);
229      result    = util_strcat3("(", tmpString, ")");
230      break;
231    case Ctlp_NOT_c:
232      tmpString = util_strcat3("(", s1, ")");
233      result    = util_strcat3("!", tmpString, "");
234      break;
235    case Ctlp_EX_c:
236      result = util_strcat3("EX(", s1, ")");
237      FREE(s1);
238      break;
239    case Ctlp_EG_c:
240      result = util_strcat3("EG(", s1, ")");
241      break;
242    case Ctlp_EF_c:
243      result = util_strcat3("EF(", s1, ")");
244      break;
245    case Ctlp_EU_c:
246      tmpString = util_strcat3("E(", s1, " U ");
247      result    = util_strcat3(tmpString, s2, ")");
248      break;
249    case Ctlp_AX_c:
250      result = util_strcat3("AX(", s1, ")");
251      break;
252    case Ctlp_AG_c:
253      result = util_strcat3("AG(", s1, ")");
254      break;
255    case Ctlp_AF_c:
256      result = util_strcat3("AF(", s1, ")");
257      break;
258    case Ctlp_AU_c:
259      tmpString = util_strcat3("A(", s1, " U ");
260      result    = util_strcat3(tmpString, s2, ")");
261      break;
262    case Ctlp_TRUE_c:
263      result = util_strsav("TRUE");
264      break;
265    case Ctlp_FALSE_c:
266      result = util_strsav("FALSE");
267      break;
268    case Ctlp_Init_c:
269      result = util_strsav("Init");
270      break;
271    case Ctlp_Cmp_c:
272      if (formula->compareValue == 0)
273        tmpString = util_strcat3("[", s1, "] = ");
274      else
275        tmpString = util_strcat3("[", s1, "] != ");
276      result    = util_strcat3(tmpString, s2, "");
277      break;
278    case Ctlp_FwdU_c:
279      tmpString = util_strcat3("FwdU(", s1, ",");
280      result    = util_strcat3(tmpString, s2, ")");
281      break;
282    case Ctlp_FwdG_c:
283      tmpString = util_strcat3("FwdG(", s1, ",");
284      result    = util_strcat3(tmpString, s2, ")");
285      break;
286    case Ctlp_EY_c:
287      result = util_strcat3("EY(", s1, ")");
288      break;
289    default:
290      fail("Unexpected type");
291  }
292
293  if (s1 != NIL(char)) {
294    FREE(s1);
295  }
296
297  if (s2 != NIL(char)) {
298    FREE(s2);
299  }
300
301  if (tmpString != NIL(char)) {
302    FREE(tmpString);
303  }
304
305  return result;
306}
307
308
309/**Function********************************************************************
310
311  Synopsis    [Prints a formula to a file.]
312
313  Description [Prints a formula to a file. All subformulas are delimited by
314  parenthesis. The syntax used is the same as used by the CTL parser.  Does
315  nothing if passed a NULL formula.]
316
317  SideEffects []
318
319******************************************************************************/
320void
321Ctlp_FormulaPrint(
322  FILE * fp,
323  Ctlp_Formula_t * formula)
324{
325  char *tmpString;
326  if (formula == NIL(Ctlp_Formula_t)) {
327    return;
328  }
329  tmpString = Ctlp_FormulaConvertToString(formula);
330  (void) fprintf(fp, "%s", tmpString);
331  FREE(tmpString);
332}
333
334
335/**Function********************************************************************
336
337  Synopsis    [Gets the type of a formula.]
338
339  Description [Gets the type of a formula. See ctlp.h for all the types. It is
340  an error to call this function on a NULL formula.]
341
342  SideEffects []
343
344  SeeAlso     []
345
346******************************************************************************/
347Ctlp_FormulaType
348Ctlp_FormulaReadType(
349  Ctlp_Formula_t * formula)
350{
351  assert( formula != NIL(Ctlp_Formula_t) );
352  return (formula->type);
353}
354
355#if 0
356boolean
357Ctlp_FormulaReadEvenNegations(
358  Ctlp_Formula_t * formula)
359{
360  assert(formula != NIL(Ctlp_Formula_t));
361  return (formula->even_negations);
362}
363#endif
364
365
366/**Function********************************************************************
367
368  Synopsis    [Gets the compare value of a formula.]
369
370  Description [Gets the compare value of a formula.  It is an error to call
371  this function on a NULL formula.]
372
373  SideEffects []
374
375  SeeAlso     []
376
377******************************************************************************/
378int
379Ctlp_FormulaReadCompareValue(
380  Ctlp_Formula_t * formula)
381{
382  int value;
383
384  assert( formula != NIL(Ctlp_Formula_t));
385  value = formula->compareValue;
386  return (value);
387}
388
389
390/**Function********************************************************************
391
392  Synopsis    [Reads the variable name of a leaf formula.]
393
394  Description [Reads the variable name of a leaf formula.
395  It is an error to call this function on a non-leaf formula.]
396
397  SideEffects []
398
399******************************************************************************/
400char *
401Ctlp_FormulaReadVariableName(
402  Ctlp_Formula_t * formula)
403{
404  if (formula->type != Ctlp_ID_c){
405    fail("Ctlp_FormulaReadVariableName() was called on a non-leaf formula.");
406  }
407  return ((char *)(formula->left));
408}
409
410
411/**Function********************************************************************
412
413  Synopsis    [Reads the value name of a leaf formula.]
414
415  Description [Reads the value name of a leaf formula.
416  It is an error to call this function on a non-leaf formula.]
417
418  SideEffects []
419
420******************************************************************************/
421char *
422Ctlp_FormulaReadValueName(
423  Ctlp_Formula_t * formula)
424{
425  if (formula->type != Ctlp_ID_c){
426    fail("Ctlp_FormulaReadValueName() was called on a non-leaf formula.");
427  }
428  return ((char *)(formula->right));
429}
430
431/**Function********************************************************************
432
433  Synopsis    [Gets the left child of a formula.]
434
435  Description [Gets the left child of a formula.  User must not free this
436  formula. If a formula is a leaf formula, NIL(Ctlp_Formula_t) is returned.]
437
438  SideEffects []
439
440  SeeAlso     [Ctlp_FormulaReadRightChild]
441
442******************************************************************************/
443Ctlp_Formula_t *
444Ctlp_FormulaReadLeftChild(
445  Ctlp_Formula_t * formula)
446{
447  if (formula->type != Ctlp_ID_c){
448    return (formula->left);
449  }
450  return NIL(Ctlp_Formula_t);
451}
452
453
454/**Function********************************************************************
455
456  Synopsis    [Gets the right child of a formula.]
457
458  Description [Gets the right child of a formula.  User must not free this
459  formula. If a formula is a leaf formula, NIL(Ctlp_Formula_t) is returned.]
460
461  SideEffects []
462
463  SeeAlso     [Ctlp_FormulaReadLeftChild]
464
465******************************************************************************/
466Ctlp_Formula_t *
467Ctlp_FormulaReadRightChild(
468  Ctlp_Formula_t * formula)
469{
470  if (formula->type != Ctlp_ID_c){
471    return (formula->right);
472  }
473  return NIL(Ctlp_Formula_t);
474}
475
476
477/**Function********************************************************************
478
479  Synopsis [Gets a copy of the set of states for which this formula is
480  true.]
481
482  Description [Gets a copy of the MDD representing the set of states for which
483  this formula is true.  It is the user's responsibility to free this MDD. If
484  the set of states has not yet been computed, then a NULL mdd_t is
485  returned. It is an error to call this function on a NULL formula.]
486
487  SideEffects []
488
489  SeeAlso     [Ctlp_FormulaSetStates]
490
491******************************************************************************/
492mdd_t *
493Ctlp_FormulaObtainStates(
494  Ctlp_Formula_t * formula)
495{
496  assert(formula != NIL(Ctlp_Formula_t));
497  if (formula->states == NIL(mdd_t) ||
498      formula->latest == Ctlp_Incomparable_c) {
499    return NIL(mdd_t);
500  }
501  else {
502    return mdd_dup(formula->states);
503  }
504}
505
506
507/**Function********************************************************************
508
509  Synopsis    [Stores the set of states with the formula.]
510
511  Description [Stores the MDD with the formula (a copy is not made,
512  and hence, the caller should not later free this MDD). This MDD is
513  intended to represent the set of states for which the formula is
514  true. It is an error to call this function on a NULL formula.]
515
516  SideEffects []
517
518  SeeAlso     [Ctlp_FormulaObtainStates]
519
520******************************************************************************/
521void
522Ctlp_FormulaSetStates(
523  Ctlp_Formula_t * formula,
524  mdd_t * states)
525{
526  assert(formula != NIL(Ctlp_Formula_t));
527  /* RB: added the next two lines.  Given the Description, this was a
528     bug */
529  if(formula->states != NIL(mdd_t))
530    mdd_free(formula->states);
531  formula->states = states;
532  formula->latest = Ctlp_Exact_c;
533}
534
535
536/**Function********************************************************************
537
538  Synopsis [Gets (a copy of) the latest approximation of the satisfying set]
539
540  Description [Gets the satisfying set or an approximation of it.  The most
541  recently computed approximation is returned.  If the
542  exact set is available, it will return that, because it is never superseded.
543  If neither exact nor approximate satisfying set is available, or
544  approx is Ctlp_Incomparable_c, it fails.]
545
546  SideEffects []
547
548  SeeAlso     [Ctlp_FormulaSetApproxStates]
549
550******************************************************************************/
551mdd_t *
552Ctlp_FormulaObtainLatestApprox(
553  Ctlp_Formula_t *formula)
554{
555  if (formula->latest == Ctlp_Exact_c)
556    return mdd_dup(formula->states);
557
558  if (formula->latest == Ctlp_Overapprox_c)
559    return mdd_dup(formula->overapprox);
560
561  if (formula->latest == Ctlp_Underapprox_c)
562    return mdd_dup(formula->underapprox);
563
564  if (formula->latest == Ctlp_Incomparable_c)
565    return mdd_dup(formula->states);
566
567  assert(0);  /* we should never get here */
568  return NIL(mdd_t);
569}
570
571
572/**Function********************************************************************
573
574  Synopsis [Gets (a copy of) an approximation of the satisfying set]
575
576  Description [Gets the required approximation of the satisfying set.  If the
577  exact set is available, it will return that.  If neither is available, or
578  approx is Ctlp_Incomparable_c, it will return NULL.]
579
580  SideEffects []
581
582  SeeAlso     [Ctlp_FormulaSetApproxStates]
583
584******************************************************************************/
585mdd_t *
586Ctlp_FormulaObtainApproxStates(
587  Ctlp_Formula_t *formula,
588  Ctlp_Approx_t approx)
589{
590  if(approx == Ctlp_Incomparable_c)
591    return NIL(mdd_t);
592
593  if (formula->states != NIL(mdd_t))
594    return mdd_dup(formula->states);
595
596  if(approx == Ctlp_Exact_c)
597    return NIL(mdd_t);
598
599  if(approx == Ctlp_Overapprox_c){
600    if(formula->overapprox == NIL(mdd_t))
601      return NIL(mdd_t);
602    else
603      return mdd_dup(formula->overapprox);
604  }
605
606  if(approx == Ctlp_Underapprox_c){
607    if(formula->underapprox == NIL(mdd_t))
608      return NIL(mdd_t);
609    else
610      return mdd_dup(formula->underapprox);
611  }
612
613  assert(0);  /* we should never get here */
614  return NIL(mdd_t);
615}
616
617
618/**Function********************************************************************
619
620  Synopsis [Stores (an approximation of) the set of states with the
621  formula.]
622
623  Description [Sets the set of states or an under or overapproximation
624  thereof, depending on the approx flag.  If there is already an under
625  or overapproximation, it is overwritten.  If the exact set is given,
626  the approx fields are cleared.  Setting an incomparable
627  approximation results in no action being taken.  An approximation
628  does not replace the exact set.  A copy of the mdd is not made, so
629  the caller should not free it.]
630
631  SideEffects []
632
633  SeeAlso     [Ctlp_FormulaObtainApproxStates Ctlp_FormulaObtainLatestApprox]
634
635******************************************************************************/
636void
637Ctlp_FormulaSetApproxStates(
638  Ctlp_Formula_t * formula,
639  mdd_t * states,
640  Ctlp_Approx_t approx)
641{
642  if (formula->latest == Ctlp_Exact_c) {
643    mdd_free(states);
644    return;
645  }
646
647  formula->latest = approx;
648
649  if (approx == Ctlp_Exact_c) {
650    if (formula->states != NIL(mdd_t))
651      mdd_free(formula->states);
652    formula->states = states;
653
654    if (formula->underapprox != NIL(mdd_t)) {
655      mdd_free(formula->underapprox);
656      formula->underapprox = NIL(mdd_t);
657    }
658
659    if (formula->overapprox != NIL(mdd_t)) {
660      mdd_free(formula->overapprox);
661      formula->overapprox = NIL(mdd_t);
662    }
663
664    return;
665  }
666
667  if (approx == Ctlp_Underapprox_c) {
668    /* you could perform a union instead, but typical use will
669       have monotonically increasing underapproximations */
670    if(formula->underapprox != NIL(mdd_t))
671      mdd_free(formula->underapprox);
672    formula->underapprox = states;
673  }
674
675  if (approx == Ctlp_Overapprox_c) {
676    /* you could perform an intersection instead */
677    if (formula->overapprox != NIL(mdd_t))
678      mdd_free(formula->overapprox);
679    formula->overapprox = states;
680  }
681
682  /* This case is possible; for instance when both children of an implication
683   * with (All, S) condition are underapproximated.  We may lose some states
684   * from the left if they are not in S.  These cause an overapproximation.
685   * We may also lose some states from the right.  These cause an
686   * underapproximation.  When the two effects are combined, we get something
687   * incomparable, yet sufficient to produce the exact result, because it is
688   * accurate over S. */
689  if (approx == Ctlp_Incomparable_c) {
690    if (formula->states != NIL(mdd_t))
691      mdd_free(formula->states);
692    formula->states = states;
693  }
694
695  return;
696}
697
698
699/**Function********************************************************************
700
701  Synopsis    [Sets the debug information of a formula.]
702
703  Description [Sets the debug information of a CTL formula.  The data is
704  uninterpreted.  FreeFn is a pointer to a function that takes a formula as
705  input and returns void.  FreeFn should free all the memory associated with
706  the debug data; it is called when this formula is freed.]
707
708  SideEffects []
709
710  SeeAlso     [Ctlp_FormulaReadDebugData]
711
712******************************************************************************/
713void
714Ctlp_FormulaSetDbgInfo(
715  Ctlp_Formula_t * formula,
716  void *data,
717  Ctlp_DbgInfoFreeFn freeFn)
718{
719  if (formula->dbgInfo.data != NIL(void)){
720    assert(formula->dbgInfo.freeFn != NULL);
721
722    (*formula->dbgInfo.freeFn)(formula);
723  }
724
725  formula->dbgInfo.data   = data;
726  formula->dbgInfo.freeFn = freeFn;
727}
728
729
730/**Function********************************************************************
731
732  Synopsis    [Returns the debug data associated with a formula.]
733
734  Description [Returns the debug data associated with a formula.  These data
735  are uninterpreted by the ctlp package.]
736
737  SideEffects []
738
739  SeeAlso     [Ctlp_FormulaSetDbgInfo]
740
741******************************************************************************/
742void *
743Ctlp_FormulaReadDebugData(
744  Ctlp_Formula_t * formula)
745{
746  return formula->dbgInfo.data;
747}
748
749
750/**Function********************************************************************
751
752  Synopsis    [Returns TRUE if formula was converted, else FALSE.]
753  from AX/AG/AU/AF]
754
755  Description [Returns TRUE if formula was converted from a formula of type
756  AG, AX, AU, AF, or EF via a call to
757  Ctlp_FormulaConvertToExistentialFormTree or
758  Ctlp_FormulaConvertToExistentialFormDAG. Otherwise, returns FALSE.]
759
760  SideEffects []
761
762******************************************************************************/
763boolean
764Ctlp_FormulaTestIsConverted(
765  Ctlp_Formula_t * formula)
766{
767  return formula->dbgInfo.convertedFlag;
768}
769
770
771/**Function********************************************************************
772
773  Synopsis    [Returns TRUE if formula contains no path quantifiers.]
774
775  Description [Test if a CTL formula has any path quantifiers in it;
776  if so return false, else true.  For a CTL formula, being quantifier-free
777  and being propositional are equivalent.]
778
779  SideEffects []
780
781******************************************************************************/
782boolean
783Ctlp_FormulaTestIsQuantifierFree(
784  Ctlp_Formula_t *formula)
785{
786  boolean lCheck;
787  boolean rCheck;
788  Ctlp_Formula_t *leftChild;
789  Ctlp_Formula_t *rightChild;
790  Ctlp_FormulaType type;
791
792  if ( formula == NIL( Ctlp_Formula_t ) ) {
793    return TRUE;
794  }
795
796  type = Ctlp_FormulaReadType( formula );
797
798  if ( ( type == Ctlp_ID_c ) ||
799       ( type == Ctlp_TRUE_c ) ||
800       ( type == Ctlp_FALSE_c ) ) {
801    return TRUE;
802  }
803
804  if ( ( type !=  Ctlp_OR_c )   &&
805       ( type !=  Ctlp_AND_c )  &&
806       ( type !=  Ctlp_NOT_c )  &&
807       ( type !=  Ctlp_THEN_c ) &&
808       ( type !=  Ctlp_XOR_c )  &&
809       ( type !=  Ctlp_EQ_c ) ) {
810    return FALSE;
811  }
812
813  leftChild = Ctlp_FormulaReadLeftChild( formula );
814  lCheck = Ctlp_FormulaTestIsQuantifierFree( leftChild );
815
816  if (lCheck == FALSE)
817    return FALSE;
818
819  rightChild = Ctlp_FormulaReadRightChild( formula );
820  rCheck = Ctlp_FormulaTestIsQuantifierFree( rightChild );
821
822  return rCheck;
823}
824
825
826/**Function********************************************************************
827
828  Synopsis    [Annotates the each node in parse tree with its negation
829  parity.]
830
831  Description [This function must be called at the top level with
832  parity = Ctlp_Even_c.  It will then annotate each node with its parity.
833  A node in a formula with sharing may have both parities and a descendant
834  of a XOR or EQ node will have both.  Only backward CTL formulae are
835  considered.]
836
837  SideEffects [changes the negation_parity fields of all nodes in the formula]
838
839******************************************************************************/
840void
841Ctlp_FormulaNegations(
842  Ctlp_Formula_t * formula,
843  Ctlp_Parity_t parity)
844{
845
846  Ctlp_FormulaType formulaType;
847  Ctlp_Formula_t *leftChild;
848  Ctlp_Formula_t *rightChild;
849  Ctlp_Parity_t newparity;
850
851  assert(formula != NIL(Ctlp_Formula_t));
852  if (formula->negation_parity == parity)
853    return; /* already done */
854  if (formula->negation_parity != Ctlp_NoParity_c)
855    parity = Ctlp_EvenOdd_c; /* reconverging paths with different parity */
856  formula->negation_parity = parity;
857
858  formulaType = Ctlp_FormulaReadType(formula);
859  leftChild = Ctlp_FormulaReadLeftChild(formula);
860  rightChild = Ctlp_FormulaReadRightChild(formula);
861
862  switch (formulaType) {
863  case Ctlp_AX_c:
864  case Ctlp_AG_c:
865  case Ctlp_AF_c:
866  case Ctlp_EX_c:
867  case Ctlp_EG_c:
868  case Ctlp_EF_c:
869    Ctlp_FormulaNegations(leftChild,parity);
870    break;
871  case Ctlp_AU_c:
872  case Ctlp_EU_c:
873  case Ctlp_OR_c:
874  case Ctlp_AND_c:
875    Ctlp_FormulaNegations(leftChild,parity);
876    Ctlp_FormulaNegations(rightChild,parity);
877    break;
878  case Ctlp_NOT_c:
879    if (parity == Ctlp_Even_c)
880      newparity = Ctlp_Odd_c;
881    else if (parity == Ctlp_Odd_c)
882      newparity = Ctlp_Even_c;
883    else newparity = Ctlp_EvenOdd_c;
884    Ctlp_FormulaNegations(leftChild,newparity);
885    break;
886  case Ctlp_THEN_c:
887    if (parity == Ctlp_Even_c)
888      newparity = Ctlp_Odd_c;
889    else if (parity == Ctlp_Odd_c)
890      newparity = Ctlp_Even_c;
891    else newparity = Ctlp_EvenOdd_c;
892    Ctlp_FormulaNegations(leftChild,newparity);
893    Ctlp_FormulaNegations(rightChild,parity);
894    break;
895  case Ctlp_XOR_c:
896  case Ctlp_EQ_c:
897    Ctlp_FormulaNegations(leftChild,Ctlp_EvenOdd_c);
898    Ctlp_FormulaNegations(rightChild,Ctlp_EvenOdd_c);
899    break;
900  default:
901      break;
902  }
903}
904
905
906/**Function********************************************************************
907
908  Synopsis    [Checks whether an ACTL formula is W-ACTL.]
909
910  Description [Test if the binary operators in an ACTL formula have at
911  least one propositional formula as one of the operands.  If not return
912  Ctlp_NONWACTL_c, else return either Ctlp_WACTLsimple_c for propositional
913  formulae or Ctlp_WACTLstate_c for formulae containing temporal operators.
914  A W-ACTL formula must contain no exitential operators and no forward
915  operators.  XOR and EQ are allowed only in propositional subformulae.]
916
917  SideEffects [none]
918
919******************************************************************************/
920Ctlp_FormulaACTLSubClass
921Ctlp_CheckIfWACTL(
922  Ctlp_Formula_t *formula)
923{
924  Ctlp_FormulaType formulaType;
925  Ctlp_Formula_t *rightFormula, *leftFormula;
926  Ctlp_FormulaACTLSubClass resultLeft, resultRight;
927
928  assert(formula != NIL(Ctlp_Formula_t));
929  if(formula == NIL(Ctlp_Formula_t))
930    return Ctlp_WACTLsimple_c;
931
932  formulaType = Ctlp_FormulaReadType(formula);
933  leftFormula = Ctlp_FormulaReadLeftChild(formula);
934  rightFormula = Ctlp_FormulaReadRightChild(formula);
935
936  /* Depending on the formula type, create result or recur. */
937  switch (formulaType) {
938  case Ctlp_AX_c:
939  case Ctlp_AG_c:
940  case Ctlp_AF_c:
941    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
942    if (resultLeft == Ctlp_NONWACTL_c)
943      return Ctlp_NONWACTL_c;
944    else
945      return Ctlp_WACTLstate_c;
946    break;
947  case Ctlp_AU_c:
948    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
949    if (resultLeft == Ctlp_NONWACTL_c)
950      return Ctlp_NONWACTL_c;
951    resultRight = Ctlp_CheckIfWACTL(rightFormula);
952    if (resultRight == Ctlp_NONWACTL_c)
953      return Ctlp_NONWACTL_c;
954    if (resultLeft == Ctlp_WACTLsimple_c || resultRight == Ctlp_WACTLsimple_c)
955      return Ctlp_WACTLstate_c;
956    else
957      return Ctlp_NONWACTL_c;
958    break;
959  case Ctlp_OR_c:
960  case Ctlp_AND_c:
961  case Ctlp_THEN_c:
962    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
963    if (resultLeft == Ctlp_NONWACTL_c) {
964      return Ctlp_NONWACTL_c;
965    } else {
966      resultRight = Ctlp_CheckIfWACTL(rightFormula);
967      if (resultRight == Ctlp_WACTLsimple_c) {
968        return resultLeft;
969      } else if (resultLeft == Ctlp_WACTLsimple_c) {
970        return resultRight;
971      } else {
972        return Ctlp_NONWACTL_c;
973      }
974    }
975    break;
976  case Ctlp_NOT_c:
977    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
978    return resultLeft;
979    break;
980  case Ctlp_XOR_c:
981  case Ctlp_EQ_c:
982    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
983    if (resultLeft != Ctlp_WACTLsimple_c) {
984      return Ctlp_NONWACTL_c;
985    } else {
986      resultRight = Ctlp_CheckIfWACTL(rightFormula);
987      if (resultRight == Ctlp_WACTLsimple_c)
988        return Ctlp_WACTLsimple_c;
989      else
990        return Ctlp_NONWACTL_c;
991    }
992    break;
993  case Ctlp_ID_c:
994  case Ctlp_TRUE_c:
995  case Ctlp_FALSE_c:
996    return Ctlp_WACTLsimple_c;
997    break;
998  default:
999    fprintf(vis_stderr, "#Ctlp Result : The formula should be in Universal operators!\n");
1000    return Ctlp_NONWACTL_c;
1001    break;
1002  }
1003} /* End of Ctlp_CheckTypeOfExistentialFormula */
1004
1005
1006/**Function********************************************************************
1007
1008  Synopsis    [Returns original formula corresponding to converted formula.]
1009
1010  SideEffects []
1011
1012******************************************************************************/
1013Ctlp_Formula_t *
1014Ctlp_FormulaReadOriginalFormula(
1015  Ctlp_Formula_t * formula)
1016{
1017  return formula->dbgInfo.originalFormula;
1018}
1019
1020
1021/**Function********************************************************************
1022
1023  Synopsis    [Frees a formula if no other formula refers to it as a
1024  sub-formula.]
1025
1026  Description [The function decrements the refCount of the formula. As a
1027  consequence, if the refCount becomes 0, the formula is freed.]
1028
1029  SideEffects []
1030
1031  SeeAlso     [CtlpFormulaFree, CtlpDecrementRefCount]
1032
1033******************************************************************************/
1034void
1035Ctlp_FormulaFree(
1036  Ctlp_Formula_t *formula)
1037{
1038  CtlpFormulaDecrementRefCount(formula);
1039}
1040
1041/**Function********************************************************************
1042
1043  Synopsis [Recursively frees states, underapprox and overapprox fields of
1044  Ctlp_Formula_t, and the debug data]
1045
1046  Description []
1047
1048  SideEffects []
1049
1050  SeeAlso     [Ctlp_FormulaFree]
1051
1052******************************************************************************/
1053void
1054Ctlp_FlushStates(
1055  Ctlp_Formula_t * formula)
1056{
1057  if (formula != NIL(Ctlp_Formula_t)) {
1058
1059    if (formula->type != Ctlp_ID_c){
1060      if (formula->left  != NIL(Ctlp_Formula_t)) {
1061        Ctlp_FlushStates(formula->left);
1062      }
1063      if (formula->right != NIL(Ctlp_Formula_t)) {
1064        Ctlp_FlushStates(formula->right);
1065      }
1066    }
1067
1068    if (formula->states != NIL(mdd_t)){
1069      mdd_free(formula->states);
1070      formula->states = NIL(mdd_t);
1071    }
1072    if (formula->underapprox != NIL(mdd_t)){
1073      mdd_free(formula->underapprox);
1074      formula->underapprox = NIL(mdd_t);
1075    }
1076    if (formula->overapprox != NIL(mdd_t)){
1077      mdd_free(formula->overapprox);
1078      formula->overapprox = NIL(mdd_t);
1079    }
1080
1081    if (formula->dbgInfo.data != NIL(void)){
1082      (*formula->dbgInfo.freeFn)(formula);
1083      formula->dbgInfo.data = NIL(void);
1084    }
1085
1086  }
1087
1088}
1089
1090/**Function********************************************************************
1091
1092
1093  Synopsis    [Duplicates a CTL formula.]
1094
1095  Description [Recursively duplicate a formula. Does nothing if the formula
1096  is NIL. Does not copy mdd for states, underapprox, overapprox, dbgInfo, and
1097  in general all the information that is used to annotate the formula.]
1098
1099  SideEffects []
1100
1101  SeeAlso     []
1102
1103******************************************************************************/
1104Ctlp_Formula_t *
1105Ctlp_FormulaDup(
1106  Ctlp_Formula_t * formula)
1107{
1108  Ctlp_Formula_t *result = NIL(Ctlp_Formula_t);
1109
1110  if ( formula == NIL(Ctlp_Formula_t)) {
1111        return NIL(Ctlp_Formula_t);
1112  }
1113
1114  result = ALLOC(Ctlp_Formula_t, 1);
1115
1116  result->type                    = formula->type;
1117  result->states                  = NIL(mdd_t);
1118  result->underapprox             = NIL(mdd_t);
1119  result->overapprox              = NIL(mdd_t);
1120  result->latest                  = Ctlp_Incomparable_c;
1121  result->Bottomstates            = NIL(array_t);
1122  result->Topstates               = NIL(array_t);
1123  result->negation_parity         = Ctlp_NoParity_c;
1124  result->leaves                  = formula->leaves == NIL(array_t) ?
1125    NIL(array_t) : array_dup(formula->leaves);
1126  result->matchfound_top          = NIL(array_t);
1127  result->matchelement_top        = NIL(array_t);
1128  result->matchfound_bot          = NIL(array_t);
1129  result->matchelement_bot        = NIL(array_t);
1130  result->refCount                = 1;
1131  result->dbgInfo.data            = NIL(void);
1132  result->dbgInfo.freeFn          = (Ctlp_DbgInfoFreeFn) NULL;
1133  result->dbgInfo.convertedFlag   = FALSE;
1134  result->dbgInfo.originalFormula = NIL(Ctlp_Formula_t);
1135  result->top                     = 0;
1136  result->compareValue            = 0;
1137
1138  if ( formula->type != Ctlp_ID_c )  {
1139    result->left                    = Ctlp_FormulaDup( formula->left );
1140    result->right                   = Ctlp_FormulaDup( formula->right );
1141  }
1142  else {
1143    result->left  = (Ctlp_Formula_t *) util_strsav((char *)formula->left );
1144    result->right = (Ctlp_Formula_t *) util_strsav((char *)formula->right );
1145  }
1146  result->share           = 1;
1147  result->BotOnionRings   = NIL(array_t);
1148  result->TopOnionRings   = NIL(array_t);
1149  return result;
1150}
1151
1152/**Function********************************************************************
1153
1154
1155  Synopsis    [Complements a CTL formula.]
1156
1157  Description []
1158
1159  SideEffects []
1160
1161  SeeAlso     []
1162
1163******************************************************************************/
1164Ctlp_Formula_t *
1165Ctlp_FormulaConverttoComplement(
1166  Ctlp_Formula_t * formula)
1167{
1168  Ctlp_Formula_t *result;
1169
1170  if (formula == NIL(Ctlp_Formula_t)) {
1171        return NIL(Ctlp_Formula_t);
1172  }
1173  result = Ctlp_FormulaCreate(Ctlp_NOT_c,formula,NIL(Ctlp_Formula_t));
1174  CtlpFormulaIncrementRefCount(formula);
1175#if 0
1176  result = FormulaCreateWithType(Ctlp_NOT_c);
1177  result->left = FormulaCreateWithType(formula->type);
1178  result->left->left = formula->left;
1179  result->left->right = formula->right;
1180  switch (formula->type) {
1181  case Ctlp_ID_c:
1182  case Ctlp_TRUE_c:
1183  case Ctlp_FALSE_c:
1184  case Ctlp_Init_c:
1185    break;
1186  default:
1187    CtlpFormulaIncrementRefCount(formula->left);
1188    CtlpFormulaIncrementRefCount(formula->right);
1189    break;
1190  }
1191#endif
1192  return result;
1193} /* Ctlp_FormulaConverttoComplement */
1194
1195
1196/**Function********************************************************************
1197
1198
1199  Synopsis    [Converts AFp to A (TRUE) U p.]
1200
1201  Description []
1202
1203  SideEffects [Should be called only for AF formula]
1204
1205  SeeAlso     []
1206
1207******************************************************************************/
1208Ctlp_Formula_t *
1209Ctlp_FormulaConvertAFtoAU(
1210  Ctlp_Formula_t * formula)
1211{
1212  Ctlp_Formula_t *result;
1213  /* AFf --> (A true U f)  */
1214  assert(formula->type == Ctlp_AF_c);
1215  result = FormulaCreateWithType(Ctlp_AU_c);
1216  result->left  = FormulaCreateWithType(Ctlp_TRUE_c);
1217  result->right = formula->left;
1218  CtlpFormulaIncrementRefCount(formula->left);
1219  return result;
1220}
1221
1222
1223/**Function********************************************************************
1224
1225
1226  Synopsis    [Converts EFp to p + EX(EFp).]
1227
1228  Description []
1229
1230  SideEffects [Should be called only for EF formula]
1231
1232  SeeAlso     []
1233
1234******************************************************************************/
1235Ctlp_Formula_t *
1236Ctlp_FormulaConvertEFtoOR(
1237  Ctlp_Formula_t * formula)
1238{
1239  Ctlp_Formula_t *result;
1240  /* EFf --> f + EX(EF(f))  */
1241  assert(formula->type == Ctlp_EF_c);
1242  result = FormulaCreateWithType(Ctlp_OR_c);
1243  result->left = formula->left;
1244  result->right = FormulaCreateWithType(Ctlp_EX_c);
1245  result->right->left = formula;
1246  CtlpFormulaIncrementRefCount(formula->left);
1247  CtlpFormulaIncrementRefCount(formula);
1248  return result;
1249}
1250
1251
1252/**Function********************************************************************
1253
1254
1255  Synopsis    [Converts EpUq to q + p*EX(EpUq).]
1256
1257  Description []
1258
1259  SideEffects [Should be called only for EU formula]
1260
1261  SeeAlso     []
1262
1263******************************************************************************/
1264Ctlp_Formula_t *
1265Ctlp_FormulaConvertEUtoOR(
1266  Ctlp_Formula_t * formula)
1267{
1268  Ctlp_Formula_t *result;
1269  assert(formula->type == Ctlp_EU_c);
1270  /* E(f1)U(f2) --> f2 + f1*EX( E(f1)U(f2) )  */
1271  result = FormulaCreateWithType(Ctlp_OR_c);
1272  result->left = formula->right;
1273  result->right = FormulaCreateWithType(Ctlp_AND_c);
1274  result->right->left = formula->left;
1275  result->right->right = FormulaCreateWithType(Ctlp_EX_c);
1276  result->right->right->left = formula;
1277  CtlpFormulaIncrementRefCount(formula->left);
1278  CtlpFormulaIncrementRefCount(formula->right);
1279  CtlpFormulaIncrementRefCount(formula);
1280  return result;
1281}
1282
1283
1284/**Function********************************************************************
1285
1286
1287  Synopsis    [Convert p^q to !p*q + p*!q.]
1288
1289  Description []
1290
1291  SideEffects [Should be called only for XOR formula]
1292
1293  SeeAlso     []
1294
1295******************************************************************************/
1296Ctlp_Formula_t *
1297Ctlp_FormulaConvertXORtoOR(
1298  Ctlp_Formula_t * formula)
1299{
1300  Ctlp_Formula_t *result;
1301  assert(formula->type == Ctlp_XOR_c);
1302  result = FormulaCreateWithType(Ctlp_OR_c);
1303  result->left = FormulaCreateWithType(Ctlp_AND_c);
1304  result->right = FormulaCreateWithType(Ctlp_AND_c);
1305  result->left->left = Ctlp_FormulaConverttoComplement(formula->left);
1306  result->left->right = formula->right;
1307  result->right->left = formula->left;
1308  result->right->right = Ctlp_FormulaConverttoComplement(formula->right);
1309  CtlpFormulaIncrementRefCount(formula->left);
1310  CtlpFormulaIncrementRefCount(formula->right);
1311  return result;
1312}
1313
1314
1315/**Function********************************************************************
1316
1317
1318  Synopsis    [Converts p<->q to p*q + !p*!q.]
1319
1320  Description []
1321
1322  SideEffects [Should be called only for EQ formula]
1323
1324  SeeAlso     []
1325
1326******************************************************************************/
1327Ctlp_Formula_t *
1328Ctlp_FormulaConvertEQtoOR(
1329  Ctlp_Formula_t * formula)
1330{
1331  Ctlp_Formula_t *result;
1332  assert(formula->type == Ctlp_EQ_c);
1333  result = FormulaCreateWithType(Ctlp_OR_c);
1334  result->left = FormulaCreateWithType(Ctlp_AND_c);
1335  result->right = FormulaCreateWithType(Ctlp_AND_c);
1336  result->left->left = formula->left;
1337  result->left->right = formula->right;
1338  result->right->left = Ctlp_FormulaConverttoComplement(formula->left);
1339  result->right->right = Ctlp_FormulaConverttoComplement(formula->right);
1340  CtlpFormulaIncrementRefCount(formula->left);
1341  CtlpFormulaIncrementRefCount(formula->right);
1342  return result;
1343}
1344
1345
1346/**Function********************************************************************
1347
1348  Synopsis    [Returns formula with a negation pushed down]
1349
1350  Description [Returns formula with a negation pushed down. It is assumed that
1351               the formula being passsed to it is not a proposition]
1352
1353  SideEffects []
1354
1355******************************************************************************/
1356Ctlp_Formula_t *
1357Ctlp_FormulaPushNegation(
1358  Ctlp_Formula_t * formula)
1359{
1360  Ctlp_Formula_t *result;
1361  if (formula == NIL(Ctlp_Formula_t)) {
1362    return NIL(Ctlp_Formula_t);
1363  }
1364
1365  switch(formula->type) {
1366    /*
1367     * The cases are listed in rough order of their expected frequency.
1368     */
1369  case Ctlp_OR_c: /*!(f1 v f2) = !f1 * !f2*/
1370    result = FormulaCreateWithType(Ctlp_AND_c);
1371    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1372    result->right = Ctlp_FormulaConverttoComplement(formula->right);
1373    break;
1374  case Ctlp_AND_c: /*!(f1 * f2) = !f1 v !f2*/
1375    result = FormulaCreateWithType(Ctlp_OR_c);
1376    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1377    result->right = Ctlp_FormulaConverttoComplement(formula->right);
1378    break;
1379  case Ctlp_THEN_c: /*!(f1 -> f2) = !(!f1 v f2) = f1 * !f2 */
1380    result = FormulaCreateWithType(Ctlp_AND_c);
1381    result->left  = formula->left;
1382    CtlpFormulaIncrementRefCount(formula->left);
1383    result->right = Ctlp_FormulaConverttoComplement(formula->right);
1384    break;
1385  case Ctlp_XOR_c: /*!(f1 ^ f2) = f1 <-> f2*/
1386    result = FormulaCreateWithType(Ctlp_EQ_c);
1387    result->left  = formula->left;
1388    result->right = formula->right;
1389    CtlpFormulaIncrementRefCount(formula->left);
1390    CtlpFormulaIncrementRefCount(formula->right);
1391    break;
1392  case Ctlp_EQ_c: /*!(f1 <-> f2) = f1 ^ f2*/
1393    result = FormulaCreateWithType(Ctlp_XOR_c);
1394    result->left  = formula->left;
1395    result->right = formula->right;
1396    CtlpFormulaIncrementRefCount(formula->left);
1397    CtlpFormulaIncrementRefCount(formula->right);
1398    break;
1399  case Ctlp_NOT_c:/* !(!f1) = f1*/
1400    result = formula->left;
1401    CtlpFormulaIncrementRefCount(formula->left);
1402    break;
1403  case Ctlp_EX_c:/* !(EX(f1)) = AX(!f1)*/
1404    result = FormulaCreateWithType(Ctlp_AX_c);
1405    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1406    break;
1407  case Ctlp_EG_c: /*!(EG(f1)) = AF(!f1)*/
1408    result = FormulaCreateWithType(Ctlp_AF_c);
1409    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1410    break;
1411  case Ctlp_EF_c: /*!(EF(f1)) = AG(!f1)*/
1412    result = FormulaCreateWithType(Ctlp_AG_c);
1413    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1414    break;
1415  case Ctlp_EU_c: /* !(EpUq) = A(!q)U(!(p+q) + AG(!q))*/
1416    result = FormulaCreateWithType(Ctlp_AU_c);
1417    result->left  = Ctlp_FormulaConverttoComplement(formula->right);
1418    result->right = FormulaCreateWithType(Ctlp_OR_c);
1419    result->right->left = FormulaCreateWithType(Ctlp_NOT_c);
1420    result->right->left->left = FormulaCreateWithType(Ctlp_OR_c);
1421    result->right->left->left->left = formula->left;
1422    result->right->left->left->right = formula->right;
1423    result->right->right = FormulaCreateWithType(Ctlp_AG_c);
1424    result->right->right->left = Ctlp_FormulaConverttoComplement(formula->right);
1425    CtlpFormulaIncrementRefCount(formula->left);
1426    CtlpFormulaIncrementRefCount(formula->right);
1427    break;
1428  case Ctlp_AX_c:/* !AX(f1) = EX(!f1)*/
1429    result = FormulaCreateWithType(Ctlp_EX_c);
1430    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1431    break;
1432  case Ctlp_AG_c:/* !AG(f1) = EF(!f1) */
1433    result = FormulaCreateWithType(Ctlp_EF_c);
1434    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1435    break;
1436  case Ctlp_AF_c: /* !AF(f1) = EG(!f1)*/
1437    result = FormulaCreateWithType(Ctlp_EG_c);
1438    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
1439    break;
1440  case Ctlp_AU_c: /* !(ApUq) = (E(!q)U(!(p+q)))+(EG!q)*/
1441    result = FormulaCreateWithType(Ctlp_OR_c);
1442    result->left = FormulaCreateWithType(Ctlp_EU_c);
1443    result->left->left  = Ctlp_FormulaConverttoComplement(formula->right);
1444    result->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1445    result->left->right->left= FormulaCreateWithType(Ctlp_OR_c);
1446    result->left->right->left->left = formula->left;
1447    result->left->right->left->right = formula->right;
1448    result->right = FormulaCreateWithType(Ctlp_EG_c);
1449    result->right->left = Ctlp_FormulaConverttoComplement(formula->right);
1450    CtlpFormulaIncrementRefCount(formula->left);
1451    CtlpFormulaIncrementRefCount(formula->right);
1452    break;
1453  case Ctlp_TRUE_c:/* !TRUE = FALSE*/
1454    result = FormulaCreateWithType(Ctlp_FALSE_c);
1455    break;
1456  case Ctlp_FALSE_c:/*!FALSE = TRUE*/
1457    result = FormulaCreateWithType(Ctlp_TRUE_c);
1458    break;
1459  case Ctlp_Init_c: /* ???*/
1460  case Ctlp_Cmp_c: /* ???*/
1461    /* if (formula->compareValue == 0)
1462        tmpString = util_strcat3("[", s1, "] = ");
1463      else
1464        tmpString = util_strcat3("[", s1, "] != ");
1465      result    = util_strcat3(tmpString, s2, "");
1466      break;*/
1467  case Ctlp_FwdU_c: /* ???*/
1468  case Ctlp_FwdG_c:  /* ??? */
1469  case Ctlp_EY_c: /* ??? */
1470    result = formula;
1471    break;
1472  default:
1473      fail("Unexpected type");
1474  }
1475
1476  return result;
1477}
1478/*****************************************************************************/
1479
1480/**Function********************************************************************
1481
1482  Synopsis    [Frees an array of CTL formulas.]
1483
1484  Description [Calls CtlpFormulaDecrementRefCount on each formula in
1485  formulaArray, and then frees the array itself. It is okay to call this
1486  function with an empty array, but it is an error to call it with a NULL
1487  array.]
1488
1489  SideEffects []
1490
1491  SeeAlso     [Ctlp_FormulaFree]
1492
1493******************************************************************************/
1494void
1495Ctlp_FormulaArrayFree(
1496  array_t * formulaArray /* of Ctlp_Formula_t */)
1497{
1498  int i;
1499  int numFormulas = array_n(formulaArray);
1500
1501  assert(formulaArray != NIL(array_t));
1502  for (i = 0; i < numFormulas; i++) {
1503    Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
1504
1505    CtlpFormulaDecrementRefCount(formula);
1506  }
1507
1508  array_free(formulaArray);
1509}
1510
1511
1512/**Function********************************************************************
1513
1514  Synopsis    [Converts a CTL formula to existential form.]
1515
1516  Description [Converts a CTL formula to existential form.  That is, all
1517  universal path quantifiers are replaced with the appropriate combination of
1518  existential quantifiers and Boolean negation.  Also converts "finally"
1519  operators to "until" operators.<p>
1520
1521  <p>Returns a new formula that shares absolutely nothing with the original
1522  formula (not even the strings). Also, the new formula does not have any MDDs
1523  associated with it.  The "originalFormula" field of each new subformula is
1524  set to point to the formula passed as an argument.  In addition, if (and only
1525  if) the original formula is of type AG, AX, AU, AF, or EF, the "converted
1526  flag" is set. Returns NULL if called with a NULL formula.
1527
1528  <p>Note: the debugger takes advantage of the exact way that the conversion is
1529  done.  Hence, you cannot play around much with the syntax of the converted
1530  formula.
1531
1532  <p>A list of conversion rules shouls be included here (RB).
1533
1534  <br> AG phi turns into !EU(true,! phi'), where the top ! has converted set
1535  and points to the AG, and phi' points to phi.
1536
1537  <br> AU?
1538
1539  <br> AX?
1540
1541  <br> Any others?
1542  ]
1543
1544  SideEffects []
1545
1546
1547  SeeAlso [Ctlp_FormulaArrayConvertToExistentialForm,
1548  Ctlp_ConvertToSimpleExistentialForm]
1549
1550******************************************************************************/
1551Ctlp_Formula_t *
1552Ctlp_FormulaConvertToExistentialForm(
1553  Ctlp_Formula_t * formula)
1554{
1555  Ctlp_Formula_t *new_;
1556  char *variableNameCopy, *valueNameCopy;
1557
1558  if (formula == NIL(Ctlp_Formula_t)) {
1559    return NIL(Ctlp_Formula_t);
1560  }
1561
1562  /*
1563   * Recursively convert each subformula.
1564   */
1565
1566  switch(formula->type) {
1567    case Ctlp_EF_c:
1568      /* EFf --> (E true U f)  */
1569      new_ = FormulaCreateWithType(Ctlp_EU_c);
1570      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
1571      new_->right = Ctlp_FormulaConvertToExistentialForm(formula->left);
1572      new_->dbgInfo.convertedFlag = TRUE;
1573      break;
1574
1575    case Ctlp_AX_c:
1576      /* AXf --> !(EX(!f)) */
1577      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1578      new_->left = FormulaCreateWithType(Ctlp_EX_c);
1579      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
1580      new_->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
1581      new_->dbgInfo.convertedFlag = TRUE;
1582      break;
1583
1584    case Ctlp_AG_c:
1585      /* AGf --> ![(E true U !f)] */
1586      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1587      new_->left = FormulaCreateWithType(Ctlp_EU_c);
1588      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
1589      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1590      new_->left->right->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
1591      new_->dbgInfo.convertedFlag = TRUE;
1592      break;
1593
1594    case Ctlp_AF_c:
1595      /* AFf --> ![EG(!f)] */
1596      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1597      new_->left = FormulaCreateWithType(Ctlp_EG_c);
1598      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
1599      new_->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
1600      new_->dbgInfo.convertedFlag = TRUE;
1601      break;
1602
1603    case Ctlp_AU_c:
1604      /* A[fUg] --> !((E[!g U (!f*!g)]) + (EG!g)) */
1605
1606      new_ = FormulaCreateWithType(Ctlp_NOT_c); /* top */
1607      new_->left = FormulaCreateWithType(Ctlp_OR_c); /* ((E[!g U (!f*!g)]) + (EG!g)) */
1608
1609      new_->left->right = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
1610      new_->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1611      new_->left->right->left->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
1612
1613      new_->left->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
1614      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1615      new_->left->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
1616      new_->left->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
1617      new_->left->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
1618      new_->left->left->right->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left); /* f */
1619      new_->left->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1620      new_->left->left->right->right->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
1621      new_->dbgInfo.convertedFlag = TRUE;
1622      break;
1623
1624    case Ctlp_ID_c:
1625      /* Make a copy of the name, and create a new formula. */
1626      variableNameCopy = util_strsav((char *)(formula->left));
1627      valueNameCopy = util_strsav((char *)(formula->right));
1628      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
1629      break;
1630
1631    case Ctlp_THEN_c:
1632    case Ctlp_EX_c:
1633    case Ctlp_EG_c:
1634    case Ctlp_EU_c:
1635    case Ctlp_OR_c:
1636    case Ctlp_AND_c:
1637    case Ctlp_NOT_c:
1638    case Ctlp_XOR_c:
1639    case Ctlp_EQ_c:
1640    case Ctlp_TRUE_c:
1641    case Ctlp_FALSE_c:
1642      /* These are already in the correct form.  Just convert subformulas. */
1643      new_ = FormulaCreateWithType(formula->type);
1644      new_->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
1645      new_->right = Ctlp_FormulaConvertToExistentialForm(formula->right);
1646      break;
1647
1648    default:
1649      fail("Unexpected type");
1650  }
1651
1652  new_->dbgInfo.originalFormula = formula;
1653  return new_;
1654}
1655
1656/**Function********************************************************************
1657
1658  Synopsis    [Converts a CTL formula to simple existential form.]
1659
1660  Description [Converts a CTL formula to simple existential form.
1661  That is, all universal path quantifiers are replaced with the
1662  appropriate combination of existential quantifiers and Boolean
1663  negation. Only `NOT' and `AND' Boolean operators are allowed.  Also
1664  converts "finally" operators to "until" operators.
1665
1666  The converted bit is set in the converted formula only when temporal
1667  operators are converted, not when boolean operators are converted.
1668
1669  A  new formula is created that needs to be freed seperately.]
1670
1671  SideEffects []
1672
1673  Remarks     [Ctl formulas in simple existential form are incompatible
1674  with the mc debug routines.  The reason is that the debug routines
1675  count on a very specific form of the converted formula to conclude
1676  what the original formula was.]
1677
1678  SeeAlso     [Ctlp_FormulaArrayConvertToExistentialForm]
1679
1680******************************************************************************/
1681Ctlp_Formula_t *
1682Ctlp_FormulaConvertToSimpleExistentialForm(
1683  Ctlp_Formula_t * formula)
1684{
1685  Ctlp_Formula_t *new_;
1686  char *variableNameCopy, *valueNameCopy;
1687
1688  if (formula == NIL(Ctlp_Formula_t)) {
1689    return NIL(Ctlp_Formula_t);
1690  }
1691
1692  /*
1693   * Recursively convert each subformula.
1694   */
1695
1696  switch(formula->type) {
1697    case Ctlp_EF_c:
1698      /* EFf --> (E true U f)  */
1699      new_ = FormulaCreateWithType(Ctlp_EU_c);
1700      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
1701      new_->right = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1702      new_->dbgInfo.convertedFlag = TRUE;
1703      break;
1704
1705    case Ctlp_AX_c:
1706      /* AXf --> !(EX(!f)) */
1707      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1708      new_->left = FormulaCreateWithType(Ctlp_EX_c);
1709      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
1710      new_->left->left->left =
1711        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1712      new_->dbgInfo.convertedFlag = TRUE;
1713      break;
1714
1715    case Ctlp_AG_c:
1716      /* AGf --> ![(E true U !f)] */
1717      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1718      new_->left = FormulaCreateWithType(Ctlp_EU_c);
1719      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
1720      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1721      new_->left->right->left =
1722        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1723      new_->dbgInfo.convertedFlag = TRUE;
1724      break;
1725
1726    case Ctlp_AF_c:
1727      /* AFf --> ![EG(!f)] */
1728      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1729      new_->left = FormulaCreateWithType(Ctlp_EG_c);
1730      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
1731      new_->left->left->left = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1732      new_->dbgInfo.convertedFlag = TRUE;
1733      break;
1734
1735    case Ctlp_AU_c:
1736      /* A[fUg] --> !(E[!g U (!f*!g)]) * !(EG!g)) */
1737
1738      new_ = FormulaCreateWithType(Ctlp_AND_c); /* top */
1739      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
1740      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
1741      new_->left->left = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
1742      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1743      new_->left->left->left->left =
1744        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
1745
1746      new_->right->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
1747      new_->right->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1748      new_->right->left->left->left =
1749        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
1750      new_->right->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
1751      new_->right->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
1752      new_->right->left->right->left->left =
1753        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left); /* f */
1754      new_->right->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
1755      new_->right->left->right->right->left =
1756        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
1757      new_->dbgInfo.convertedFlag = TRUE;
1758      break;
1759
1760    case Ctlp_ID_c:
1761      /* Make a copy of the name, and create a new formula. */
1762      variableNameCopy = util_strsav((char *)(formula->left));
1763      valueNameCopy = util_strsav((char *)(formula->right));
1764      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
1765      break;
1766
1767      /* RB: I think THEN (and also OR, and maybe some others) should also have converted set. */
1768    case Ctlp_THEN_c:
1769      /* p->q --> !(p * !q) */
1770      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1771      new_->left = FormulaCreateWithType(Ctlp_AND_c);
1772      new_->left->left =
1773        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1774      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1775      new_->left->right->left =
1776        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1777      break;
1778
1779    case Ctlp_EX_c:
1780    case Ctlp_EG_c:
1781    case Ctlp_EU_c:
1782    case Ctlp_AND_c:
1783    case Ctlp_NOT_c:
1784    case Ctlp_TRUE_c:
1785    case Ctlp_FALSE_c:
1786      /* These are already in the correct form.  Just convert subformulas. */
1787      new_ = FormulaCreateWithType(formula->type);
1788      new_->left = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1789      new_->right = Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1790      break;
1791
1792    case Ctlp_OR_c:
1793      /* p + q --> !(!p * !q) */
1794      new_ = FormulaCreateWithType(Ctlp_NOT_c);
1795      new_->left = FormulaCreateWithType(Ctlp_AND_c);
1796      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
1797      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1798      new_->left->left->left =
1799        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1800      new_->left->right->left =
1801        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1802      break;
1803    case Ctlp_XOR_c:
1804      /* p ^ q --> !(p * q) * !(!p * !q) */
1805      new_ = FormulaCreateWithType(Ctlp_AND_c);
1806      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
1807      new_->left->left = FormulaCreateWithType(Ctlp_AND_c);
1808      new_->left->left->left =
1809        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1810      new_->left->left->right =
1811        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1812      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
1813      new_->right->left = FormulaCreateWithType(Ctlp_AND_c);
1814      new_->right->left->left =  FormulaCreateWithType(Ctlp_NOT_c);
1815      new_->right->left->left->left =
1816        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1817      new_->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1818      new_->right->left->right->left =
1819        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1820      break;
1821
1822    case Ctlp_EQ_c:
1823      /* p <-> q --> !(p * !q) * !(!p * q) */
1824      new_ = FormulaCreateWithType(Ctlp_AND_c);
1825      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
1826      new_->left->left = FormulaCreateWithType(Ctlp_AND_c);
1827      new_->left->left->left =
1828        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1829      new_->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
1830      new_->left->left->right->left =
1831        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1832      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
1833      new_->right->left = FormulaCreateWithType(Ctlp_AND_c);
1834      new_->right->left->left =  FormulaCreateWithType(Ctlp_NOT_c);
1835      new_->right->left->left->left =
1836        Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
1837      new_->right->left->right =
1838        Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
1839      break;
1840
1841    default:
1842      fail("Unexpected type");
1843  }
1844
1845  new_->dbgInfo.originalFormula = formula;
1846  return new_;
1847}
1848
1849/**Function********************************************************************
1850
1851  Synopsis    [Converts an array of CTL formulas to existential form.]
1852
1853  Description [Calls Ctlp_FormulaConvertToExistentialForm on each formula. It
1854  is okay to call this function with an empty array (in which case an empty
1855  array is returned), but it is an error to call it with a NULL array.
1856
1857  All formulas in the array are copied, and hence Ctlp_FormulaArrayFree() needs
1858  to be called on the result at the end.]
1859
1860  SideEffects []
1861
1862  SeeAlso [Ctlp_FormulaConvertToExistentialForm]
1863
1864******************************************************************************/
1865array_t *
1866Ctlp_FormulaArrayConvertToExistentialFormTree(
1867  array_t * formulaArray /* of Ctlp_Formula_t  */)
1868{
1869  int i;
1870  int numFormulas = array_n(formulaArray);
1871  array_t *convertedArray = array_alloc(Ctlp_Formula_t *, numFormulas);
1872
1873  assert(formulaArray != NIL(array_t));
1874
1875  for (i = 0; i < numFormulas; i++) {
1876    Ctlp_Formula_t *formula          = array_fetch(Ctlp_Formula_t *, formulaArray, i);
1877    Ctlp_Formula_t *convertedFormula = Ctlp_FormulaConvertToExistentialForm(formula);
1878
1879    array_insert(Ctlp_Formula_t *, convertedArray, i, convertedFormula);
1880  }
1881
1882  return convertedArray;
1883}
1884
1885/**Function********************************************************************
1886
1887  Synopsis    [Converts an array of CTL formulas to simple existential form.]
1888
1889  Description [Calls Ctlp_FormulaConvertToSimpleExistentialForm on
1890  each formula.  It is okay to call this function with an empty array
1891  (in which case an empty array is returned), but it is an error to
1892  call it with a NULL array.]
1893
1894  SideEffects []
1895
1896  SeeAlso     [Ctlp_FormulaConvertToExistentialForm]
1897
1898******************************************************************************/
1899array_t *
1900Ctlp_FormulaArrayConvertToSimpleExistentialFormTree(
1901  array_t * formulaArray /* of Ctlp_Formula_t  */)
1902{
1903  int i;
1904  int numFormulas;
1905  array_t *convertedArray;
1906
1907  assert( formulaArray != NIL(array_t));
1908
1909  numFormulas = array_n(formulaArray);
1910  convertedArray = array_alloc(Ctlp_Formula_t *, numFormulas);
1911
1912  for (i = 0; i < numFormulas; i++) {
1913    Ctlp_Formula_t *formula;
1914    Ctlp_Formula_t *convertedFormula;
1915
1916    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
1917    convertedFormula = Ctlp_FormulaConvertToSimpleExistentialForm(formula);
1918
1919    array_insert(Ctlp_Formula_t *, convertedArray, i, convertedFormula);
1920  }
1921
1922  return convertedArray;
1923}
1924
1925/**Function********************************************************************
1926
1927  Synopsis    [Converts an array of CTL formulae to a multi-rooted DAG.]
1928
1929  Description [The function hashes each subformula of a formula
1930  (including the formula itself) into a uniqueTable.  It returns an
1931  array containing the roots of the multi-rooted DAG thus created by
1932  the sharing of the subformulae.  It is okay to call this function
1933  with an empty array (in which case an empty array is returned), but
1934  it is an error to call it with a NULL array.]
1935
1936  SideEffects [A formula in formulaArray might be freed if it had been
1937  encountered as a subformula of some other formula. Other formulae in
1938  formulaArray might be present in the returned array. Therefore, the
1939  formulae in formulaArray should not be freed. Only formulaArray
1940  itself should be freed.
1941
1942
1943
1944  RB:  What does that mean?
1945
1946  I understand this as follows.  Copies of the formulae are not made,
1947  but rather pointers to the argument subformulae are kept.  Hence, not only
1948  should the formulae in the result not be freed, but also you cannot free the
1949  argument before you are done with the result.  Furthermore, by invocation of
1950  this function, the argument gets altered.  It is still valid, but pointers
1951  may have changed.  Is this correct?
1952
1953
1954  RB rewrite: A formula in formulaArray is freed if it is encountered as a
1955  subformula of some other formula. Other formulae in formulaArray might be
1956  present in the returned array. Therefore, the formulae in formulaArray should
1957  not be freed. Only formulaArray itself should be freed.]
1958
1959  SeeAlso     []
1960
1961******************************************************************************/
1962array_t *
1963Ctlp_FormulaArrayConvertToDAG(
1964  array_t *formulaArray)
1965{
1966  int i;
1967  Ctlp_Formula_t *formula, *uniqueFormula;
1968  st_table *uniqueTable = st_init_table(FormulaCompare, FormulaHash);
1969  int numFormulae = array_n(formulaArray);
1970  array_t *rootsOfFormulaDAG = array_alloc(Ctlp_Formula_t *, numFormulae);
1971
1972  assert(formulaArray != NIL(array_t));
1973
1974  for(i=0; i < numFormulae; i++) {
1975    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
1976    uniqueFormula = FormulaHashIntoUniqueTable(formula, uniqueTable);
1977    if(uniqueFormula != formula) {
1978      CtlpFormulaDecrementRefCount(formula);
1979      CtlpFormulaIncrementRefCount(uniqueFormula);
1980      array_insert(Ctlp_Formula_t *, rootsOfFormulaDAG, i, uniqueFormula);
1981    }
1982    else
1983      array_insert(Ctlp_Formula_t *, rootsOfFormulaDAG, i, formula);
1984  }
1985  st_free_table(uniqueTable);
1986  return rootsOfFormulaDAG;
1987}
1988
1989/**Function********************************************************************
1990
1991  Synopsis    [Converts a DAG of CTL formulae to a DAG of existential CTL
1992  formulae.]
1993
1994  Description [The function converts a DAG of CTL formulae to a DAG of
1995  existential CTL formulae. The function recursively converts each
1996  subformula of each of the formulae in the DAG and remembers the
1997  converted formula in the field states. It is okay to call this
1998  function with an empty array (in which case an empty array is
1999  returned), but it is an error to call it with a NULL array.
2000
2001  The states fileds in the formula need to be NULL.]
2002
2003  SideEffects []
2004
2005  SeeAlso     [FormulaConvertToExistentialDAG]
2006
2007******************************************************************************/
2008array_t *
2009Ctlp_FormulaDAGConvertToExistentialFormDAG(
2010  array_t *formulaDAG)
2011{
2012  int i;
2013  Ctlp_Formula_t *formula;
2014  int numFormulae = array_n(formulaDAG);
2015  array_t *existentialFormulaDAG = array_alloc(Ctlp_Formula_t *, numFormulae);
2016
2017  assert( formulaDAG != NIL(array_t));
2018
2019  for(i=0; i<numFormulae; i++) {
2020    formula = array_fetch(Ctlp_Formula_t *, formulaDAG, i);
2021    array_insert(Ctlp_Formula_t *, existentialFormulaDAG, i,
2022                 FormulaConvertToExistentialDAG(formula));
2023  }
2024  for(i=0; i<numFormulae; i++) {
2025    formula = array_fetch(Ctlp_Formula_t *, formulaDAG, i);
2026    CtlpFormulaSetStatesToNULL(formula);
2027  }
2028  return existentialFormulaDAG;
2029}
2030
2031
2032/**Function********************************************************************
2033
2034  Synopsis    [Creates a CTL formula with the specified fields.]
2035
2036  Description [Allocates a Ctlp_Formula_t, and sets the 2 fields given as
2037  arguments.  If the type is Ctlp_ID_c, then the left and right fields
2038  should contain a pointer to a variable name and a pointer to a value
2039  respectively. Otherwise, the two fields point to subformulas. refCount is
2040  set to 1. The states field is set to NULL, the converted flag is set to
2041  FALSE, and the originalFormula field is set to NULL.]
2042
2043  Comment     []
2044
2045  SideEffects []
2046
2047  SeeAlso     [CtlpFormulaDecrementRefCount]
2048
2049******************************************************************************/
2050Ctlp_Formula_t *
2051Ctlp_FormulaCreate(
2052  Ctlp_FormulaType  type,
2053  void * left,
2054  void * right)
2055{
2056  Ctlp_Formula_t *formula = ALLOC(Ctlp_Formula_t, 1);
2057
2058  formula->type                    = type;
2059  formula->left                    = (Ctlp_Formula_t *)left;
2060  formula->right                   = (Ctlp_Formula_t *)right;
2061  formula->refCount                = 1;
2062  formula->states                  = NIL(mdd_t);
2063  formula->underapprox             = NIL(mdd_t);
2064  formula->overapprox              = NIL(mdd_t);
2065  formula->Topstates               = NIL(array_t);
2066  formula->Bottomstates            = NIL(array_t);
2067  formula->leaves                  = NIL(array_t);
2068  formula->matchfound_top          = NIL(array_t);
2069  formula->matchelement_top        = NIL(array_t);
2070  formula->matchfound_bot          = NIL(array_t);
2071  formula->matchelement_bot        = NIL(array_t);
2072  formula->negation_parity         = Ctlp_NoParity_c;
2073  formula->share                   = 1;
2074  formula->dbgInfo.data            = NIL(void);
2075  formula->dbgInfo.freeFn          = (Ctlp_DbgInfoFreeFn) NULL;
2076  formula->dbgInfo.convertedFlag   = FALSE;
2077  formula->dbgInfo.originalFormula = NIL(Ctlp_Formula_t);
2078  formula->top                     = 0;
2079  formula->compareValue            = 0;
2080  formula->latest                  = Ctlp_Incomparable_c;
2081  formula->BotOnionRings           = NIL(array_t);
2082  formula->TopOnionRings           = NIL(array_t);
2083
2084  return formula;
2085}
2086
2087
2088/**Function********************************************************************
2089
2090  Synopsis    [Creates a CTL formula with disjunction of atomic propositions]
2091
2092  Description [This function returns Ctlp_Formula_t for name = {v1,v2,...}.
2093  In case of failure, a NULL pointer is returned.]
2094
2095  SideEffects []
2096
2097  SeeAlso     []
2098
2099******************************************************************************/
2100Ctlp_Formula_t *
2101Ctlp_FormulaCreateOr(
2102  char *name,
2103  char *valueStr)
2104{
2105  Ctlp_Formula_t *formula, *tempFormula;
2106  char *preStr;
2107
2108  preStr = strtok(valueStr,",");
2109  formula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
2110                               util_strsav(preStr));
2111  if (formula == NIL(Ctlp_Formula_t)) {
2112     return NIL(Ctlp_Formula_t);
2113  }
2114  while ((preStr = strtok(NIL(char),",")) != NIL(char)) {
2115    tempFormula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
2116                                     util_strsav(preStr));
2117    if (tempFormula == NIL(Ctlp_Formula_t)) {
2118      Ctlp_FormulaFree(formula);
2119      return NIL(Ctlp_Formula_t);
2120    }
2121    formula = Ctlp_FormulaCreate(Ctlp_OR_c,formula,tempFormula);
2122  }
2123  return formula;
2124}
2125
2126
2127/**Function********************************************************************
2128
2129  Synopsis    [Creates a CTL formula with conjunction of atomic propositions]
2130
2131  Description [This function returns Ctlp_Formula_t for nameVector = value,
2132  nameVector is a form of var[i:j] or var<j:j> and value is any integer n or
2133  binary string starting with 'b', for instance, b0011. If n is not
2134  fitted in var[i:j] or size of binary string is not matched with
2135  var[i:j], NULL pointer is returned]
2136
2137  SideEffects []
2138
2139  SeeAlso     []
2140
2141******************************************************************************/
2142Ctlp_Formula_t *
2143Ctlp_FormulaCreateVectorAnd(
2144  char *nameVector,
2145  char *value)
2146{
2147  Ctlp_Formula_t *formula, *tempFormula;
2148  int startValue, endValue, inc, i,j, interval,startInd;
2149  char *binValueStr, *varName, *name;
2150  char *bitValue;
2151
2152  varName = CtlpGetVectorInfoFromStr(nameVector,&startValue,&endValue,&interval,&inc);
2153  binValueStr = ALLOC(char,interval+1);
2154  if (!CtlpStringChangeValueStrToBinString(value,binValueStr,interval) ){
2155    FREE(varName);
2156    FREE(binValueStr);
2157    return NIL(Ctlp_Formula_t);
2158  }
2159
2160  name = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
2161  (void) sprintf(name,"%s[%d]",varName,startValue);
2162  (void) CtlpChangeBracket(name);
2163
2164  bitValue = ALLOC(char,2);
2165  bitValue[0] = binValueStr[0];
2166  bitValue[1] = '\0';
2167
2168  formula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
2169                               util_strsav(bitValue));
2170  j = 0;
2171  startInd = startValue;
2172  for(i=startValue;i!=endValue;i=i+inc){
2173    startInd += inc;
2174    j++;
2175    (void) sprintf(name,"%s[%d]",varName,startInd);
2176    (void) CtlpChangeBracket(name);
2177    bitValue[0] = binValueStr[j];
2178    tempFormula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
2179                                     util_strsav(bitValue));
2180    formula = Ctlp_FormulaCreate(Ctlp_AND_c,formula,tempFormula);
2181  }
2182  FREE(varName);
2183  FREE(name);
2184  FREE(binValueStr);
2185  FREE(bitValue);
2186  return formula;
2187}
2188
2189
2190/**Function********************************************************************
2191
2192  Synopsis    [Creates a CTL formula with OR of Vector AND]
2193
2194  Description [This function returns Ctlp_Formula_t for nameVector = valueStr,
2195  nameVector is a form of var[i:j] or var<j:j>, valueStr is "k,l,...,q",
2196  and k,l,...,q is either integer or binary string.  Binary string starting
2197  with 'b', for instance, b0011. If n is not fitted in var[i:j] or size of
2198  binary string is not matched with var[i:j], NULL pointer is returned]
2199
2200  SideEffects []
2201
2202  SeeAlso     []
2203
2204******************************************************************************/
2205Ctlp_Formula_t *
2206Ctlp_FormulaCreateVectorOr(
2207  char *nameVector,
2208  char *valueStr)
2209{
2210  Ctlp_Formula_t *formula,*tempFormula;
2211  char *preStr;
2212
2213  preStr = strtok(valueStr,",");
2214  formula = Ctlp_FormulaCreateVectorAnd(nameVector,preStr);
2215  if ( formula == NIL(Ctlp_Formula_t)){
2216    return NIL(Ctlp_Formula_t);
2217  }
2218  while( (preStr = strtok(NIL(char),",")) != NIL(char) ){
2219    tempFormula = Ctlp_FormulaCreateVectorAnd(nameVector,preStr);
2220    if ( tempFormula == NIL(Ctlp_Formula_t)){
2221      Ctlp_FormulaFree(formula);
2222      return NIL(Ctlp_Formula_t);
2223    }
2224    formula = Ctlp_FormulaCreate(Ctlp_OR_c,formula,tempFormula);
2225  }
2226  return formula;
2227}
2228
2229
2230/**Function********************************************************************
2231
2232  Synopsis    [Creates a CTL formula for equivalent property]
2233
2234  Description [This function assumes that each child is defined in binary
2235  domain. Enumerate type is not supported]
2236
2237  SideEffects []
2238
2239  SeeAlso     []
2240
2241******************************************************************************/
2242Ctlp_Formula_t *
2243Ctlp_FormulaCreateEquiv(
2244   char *left,
2245   char *right)
2246{
2247   Ctlp_Formula_t *formula,*formula1,*formula2;
2248
2249   char *one;
2250   char *zero;
2251
2252   one = "1";
2253   zero = "0";
2254
2255   formula1 = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(left),
2256                                 util_strsav(one));
2257   formula2 = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(right),
2258                                 util_strsav(zero));
2259   formula = Ctlp_FormulaCreate(Ctlp_XOR_c,formula1,formula2);
2260   return formula;
2261}
2262
2263/**Function********************************************************************
2264
2265  Synopsis    [Creates a CTL formula for equivalent of vector]
2266
2267  Description [This function returns a formula, which is the AND of a bitwise
2268  equivalence]
2269
2270  SideEffects []
2271
2272  SeeAlso     []
2273
2274******************************************************************************/
2275Ctlp_Formula_t *
2276Ctlp_FormulaCreateVectorEquiv(
2277  char *left,
2278  char *right)
2279{
2280  Ctlp_Formula_t *formula,*tempFormula;
2281  char *leftName,*rightName;
2282  char *leftVar, *rightVar;
2283  int  leftStart,leftEnd,rightStart,rightEnd,leftInterval,rightInterval;
2284  int  leftInc,rightInc,leftInd,rightInd,i;
2285
2286  leftName  = CtlpGetVectorInfoFromStr(left,&leftStart,&leftEnd,&leftInterval,&leftInc);
2287  rightName = CtlpGetVectorInfoFromStr(right,&rightStart,&rightEnd,&rightInterval,&rightInc);
2288  if (leftInterval != rightInterval){
2289     return NIL(Ctlp_Formula_t);
2290  }
2291  leftVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
2292  (void) sprintf(leftVar,"%s[%d]",leftName,leftStart);
2293  (void) CtlpChangeBracket(leftVar);
2294  rightVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
2295  (void) sprintf(rightVar,"%s[%d]",rightName,rightStart);
2296  (void) CtlpChangeBracket(rightVar);
2297
2298  formula = Ctlp_FormulaCreateEquiv(leftVar,rightVar);
2299  leftInd  = leftStart;
2300  rightInd = rightStart;
2301  for(i=leftStart;i!=leftEnd;i+=leftInc){
2302     leftInd  += leftInc;
2303     rightInd += rightInc;
2304     (void) sprintf(leftVar,"%s[%d]",leftName,leftInd);
2305     (void) CtlpChangeBracket(leftVar);
2306     (void) sprintf(rightVar,"%s[%d]",rightName,rightInd);
2307     (void) CtlpChangeBracket(rightVar);
2308     tempFormula = Ctlp_FormulaCreateEquiv(leftVar,rightVar);
2309     formula = Ctlp_FormulaCreate(Ctlp_AND_c,formula,tempFormula);
2310  }
2311  FREE(leftName);
2312  FREE(rightName);
2313  FREE(leftVar);
2314  FREE(rightVar);
2315  return formula;
2316}
2317
2318
2319/**Function********************************************************************
2320
2321  Synopsis    [Creates a CTL formula for multiple AX]
2322
2323  Description [This function returns a formula, which is the multiple
2324  times of AX. The given string includes the number of depth]
2325
2326  SideEffects []
2327
2328  SeeAlso     []
2329
2330******************************************************************************/
2331Ctlp_Formula_t *
2332Ctlp_FormulaCreateAXMult(
2333  char *string,
2334  Ctlp_Formula_t *formula)
2335{
2336  int i,num;
2337  char *str, *ptr;
2338  Ctlp_Formula_t *result;
2339  str = strchr(string,':');
2340  if ( str == NULL) return(NIL(Ctlp_Formula_t));
2341  str++;
2342
2343  num = strtol(str,&ptr,0);
2344
2345  if (num<=0){
2346    return (NIL(Ctlp_Formula_t));
2347  }
2348  result = Ctlp_FormulaCreate(Ctlp_AX_c,formula,NIL(Ctlp_Formula_t));
2349  for(i=1;i<num;i++){
2350    result = Ctlp_FormulaCreate(Ctlp_AX_c,result,NIL(Ctlp_Formula_t));
2351  }
2352  return result;
2353}
2354
2355
2356/**Function********************************************************************
2357
2358  Synopsis    [Creates a CTL formula for multiple EX]
2359
2360  Description [This function returns a formula, which is the multiple
2361  times of EX. The given string includes the number of depth]
2362
2363  SideEffects []
2364
2365  SeeAlso     []
2366
2367******************************************************************************/
2368Ctlp_Formula_t *
2369Ctlp_FormulaCreateEXMult(
2370  char *string,
2371  Ctlp_Formula_t *formula)
2372{
2373  int i, num;
2374  char *str, *ptr;
2375  Ctlp_Formula_t *result;
2376  str = strchr(string,':');
2377  if ( str == NULL) return(NIL(Ctlp_Formula_t));
2378  str++;
2379
2380  num = strtol(str,&ptr,0);
2381
2382  if (num<=0){
2383    return (NIL(Ctlp_Formula_t));
2384  }
2385  result = Ctlp_FormulaCreate(Ctlp_EX_c,formula,NIL(Ctlp_Formula_t));
2386  for(i=1;i<num;i++){
2387    result = Ctlp_FormulaCreate(Ctlp_EX_c,result,NIL(Ctlp_Formula_t));
2388  }
2389  return result;
2390}
2391
2392/**Function********************************************************************
2393
2394  Synopsis [Converts an array of CTL formulae to forward form.]
2395
2396  Description [Converts an array of CTL formulae to forward.  Creates a
2397  maximally shared representation if noshare is false, a representation without
2398  any sharing otherwise. ]
2399
2400  SideEffects []
2401
2402  SeeAlso     []
2403
2404******************************************************************************/
2405array_t *
2406Ctlp_FormulaArrayConvertToForward(array_t *formulaArray, int singleInitial,
2407                                  boolean doNotShareFlag)
2408{
2409  int i;
2410  Ctlp_Formula_t *formula, *existentialFormula, *forwardFormula;
2411  int numFormulae = array_n(formulaArray);
2412  array_t *forwardFormulaArray = array_alloc(Ctlp_Formula_t *, numFormulae);
2413  array_t *forwardDagArray;
2414  int compareValue;
2415
2416  for(i=0; i < numFormulae; i++) {
2417    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
2418    existentialFormula = Ctlp_FormulaConvertToExistentialForm(formula);
2419    assert(existentialFormula != NIL(Ctlp_Formula_t));
2420    formula = NIL(Ctlp_Formula_t);
2421   /*
2422    ** compareValue = 0 : check with FALSE
2423    ** compareValue = 1 : check with not-FALSE
2424    */
2425    if (singleInitial)
2426      compareValue = FormulaGetCompareValue(existentialFormula);
2427    else
2428      compareValue = 0;
2429    forwardFormula = FormulaCreateWithType(Ctlp_AND_c);
2430    forwardFormula->left = FormulaCreateWithType(Ctlp_Init_c);
2431    if (compareValue == 0) {
2432      forwardFormula->right = FormulaCreateWithType(Ctlp_NOT_c);
2433      forwardFormula->right->left = existentialFormula;
2434    } else
2435      forwardFormula->right = existentialFormula;
2436    forwardFormula->right->states = (mdd_t *)forwardFormula;
2437    /* if formula was converted before, keep that reference */
2438    if(existentialFormula->dbgInfo.originalFormula != NIL(Ctlp_Formula_t))
2439      forwardFormula->dbgInfo.originalFormula =
2440        existentialFormula->dbgInfo.originalFormula;
2441    else
2442      forwardFormula->dbgInfo.originalFormula = existentialFormula;
2443
2444    forwardFormula->top = 1;
2445    forwardFormula->compareValue = compareValue;
2446    FormulaConvertToForward(forwardFormula->right, compareValue);
2447    CtlpFormulaSetStatesToNULL(forwardFormula);
2448    FormulaInsertForwardCompareNodes(forwardFormula, NULL, compareValue);
2449    array_insert(Ctlp_Formula_t *, forwardFormulaArray, i, forwardFormula);
2450  }
2451
2452  if (doNotShareFlag)
2453    return(forwardFormulaArray);
2454
2455  forwardDagArray = Ctlp_FormulaArrayConvertToDAG(forwardFormulaArray);
2456  array_free(forwardFormulaArray);
2457  return forwardDagArray;
2458}
2459
2460
2461/**Function********************************************************************
2462
2463  Synopsis    [Returns a string for each formula type.]
2464
2465  Description [Returns a string for each formula type.]
2466
2467  SideEffects []
2468
2469  SeeAlso     []
2470
2471******************************************************************************/
2472char *
2473Ctlp_FormulaGetTypeString(Ctlp_Formula_t *formula)
2474{
2475  char *result;
2476
2477  switch(formula->type) {
2478    /*
2479     * The cases are listed in rough order of their expected frequency.
2480     */
2481    case Ctlp_ID_c:
2482      result = util_strsav("ID");
2483      break;
2484    case Ctlp_OR_c:
2485      result = util_strsav("OR");
2486      break;
2487    case Ctlp_AND_c:
2488      result = util_strsav("AND");
2489      break;
2490    case Ctlp_THEN_c:
2491      result = util_strsav("THEN");
2492      break;
2493    case Ctlp_XOR_c:
2494      result = util_strsav("XOR");
2495      break;
2496    case Ctlp_EQ_c:
2497      result = util_strsav("EQ");
2498      break;
2499    case Ctlp_NOT_c:
2500      result = util_strsav("NOT");
2501      break;
2502    case Ctlp_EX_c:
2503      result = util_strsav("EX");
2504      break;
2505    case Ctlp_EG_c:
2506      result = util_strsav("EG");
2507      break;
2508    case Ctlp_EF_c:
2509      result = util_strsav("EF");
2510      break;
2511    case Ctlp_EU_c:
2512      result = util_strsav("EU");
2513      break;
2514    case Ctlp_AX_c:
2515      result = util_strsav("AX");
2516      break;
2517    case Ctlp_AG_c:
2518      result = util_strsav("AG");
2519      break;
2520    case Ctlp_AF_c:
2521      result = util_strsav("AF");
2522      break;
2523    case Ctlp_AU_c:
2524      result = util_strsav("AU");
2525      break;
2526    case Ctlp_TRUE_c:
2527      result = util_strsav("TRUE");
2528      break;
2529    case Ctlp_FALSE_c:
2530      result = util_strsav("FALSE");
2531      break;
2532    case Ctlp_Init_c:
2533      result = util_strsav("Init");
2534      break;
2535    case Ctlp_Cmp_c:
2536      result = util_strsav("Cmp");
2537      break;
2538    case Ctlp_FwdU_c:
2539      result = util_strsav("FwdU");
2540      break;
2541    case Ctlp_FwdG_c:
2542      result = util_strsav("FwdG");
2543      break;
2544    case Ctlp_EY_c:
2545      result = util_strsav("EY");
2546      break;
2547    case Ctlp_EH_c:
2548      result = util_strsav("EH");
2549      break;
2550    default:
2551      fail("Unexpected type");
2552  }
2553  return(result);
2554}
2555
2556
2557/**Function********************************************************************
2558
2559  Synopsis           [Tests if a formula is quantifier-free, ACTL, ECTL or
2560  mixed.]
2561
2562  Description [Tests if a formula is Quantifier free, ACTL, ECTL or mixed.  We
2563  assume that the formula is in existential normal form, and hence only
2564  contains existential temporal operators.
2565
2566  <p>The formula is ECTL if every temporal operator appears under an even
2567  number of negations, and it is ACTL if every temporal operator appears under
2568  an odd number of negations.  It is quantifier-free if it is both ECTL and
2569  ACTL (i.e., no temporal operators occur), and it is mixed if it is neither
2570  ECTL nor ACTL.]
2571
2572  SideEffects        []
2573
2574  SeeAlso            []
2575
2576******************************************************************************/
2577Ctlp_FormulaClass
2578Ctlp_CheckClassOfExistentialFormula(
2579  Ctlp_Formula_t *formula)
2580{
2581  Ctlp_FormulaType formulaType;
2582  Ctlp_Formula_t *rightFormula, *leftFormula;
2583  Ctlp_FormulaClass resultLeft, resultRight, tempResult, currentClass;
2584
2585  assert(formula != NIL(Ctlp_Formula_t));
2586  if(formula == NIL(Ctlp_Formula_t))
2587    return Ctlp_QuantifierFree_c;
2588
2589  formulaType = Ctlp_FormulaReadType(formula);
2590  leftFormula = Ctlp_FormulaReadLeftChild(formula);
2591  rightFormula = Ctlp_FormulaReadRightChild(formula);
2592
2593  /* Depending on the formula type, create result or recur */
2594  switch (formulaType) {
2595  case Ctlp_EX_c:
2596  case Ctlp_EG_c:
2597  case Ctlp_EF_c:
2598  case Ctlp_EU_c:
2599  case Ctlp_FwdU_c:
2600  case Ctlp_FwdG_c:
2601  case Ctlp_EY_c:
2602  case Ctlp_EH_c:
2603    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
2604    if (formulaType == Ctlp_EU_c || formulaType == Ctlp_FwdU_c ||
2605        formulaType == Ctlp_FwdG_c )
2606      resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
2607    else
2608      resultRight = Ctlp_QuantifierFree_c;
2609
2610    tempResult = CtlpResolveClass(resultLeft, resultRight);
2611    currentClass = Ctlp_ECTL_c;
2612    return CtlpResolveClass(currentClass, tempResult);
2613  case Ctlp_AX_c:
2614  case Ctlp_AG_c:
2615  case Ctlp_AF_c:
2616  case Ctlp_AU_c:
2617    /* The formula is supposed to be only existential */
2618    fprintf(vis_stdout,
2619            "** Ctlp Error: unexpected (universal) operator type\n");
2620    assert(0);
2621    return Ctlp_Mixed_c;
2622  case Ctlp_OR_c:
2623  case Ctlp_AND_c:
2624    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
2625    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
2626    return CtlpResolveClass(resultLeft, resultRight);
2627  case Ctlp_NOT_c:
2628    tempResult = Ctlp_CheckClassOfExistentialFormula(leftFormula);
2629    return CtlpNegateFormulaClass(tempResult);
2630   case Ctlp_THEN_c:
2631    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
2632    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
2633    tempResult = CtlpNegateFormulaClass(resultLeft);
2634    return CtlpResolveClass(tempResult, resultRight);
2635  case Ctlp_XOR_c:
2636  case Ctlp_EQ_c:
2637    resultLeft =  Ctlp_CheckClassOfExistentialFormula(leftFormula);
2638    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
2639    tempResult = CtlpResolveClass(resultLeft, resultRight);
2640    if( tempResult == Ctlp_QuantifierFree_c)
2641      return Ctlp_QuantifierFree_c;
2642    else
2643      return Ctlp_Mixed_c;
2644  case Ctlp_ID_c:
2645  case Ctlp_TRUE_c:
2646  case Ctlp_FALSE_c:
2647  case Ctlp_Init_c:
2648     return Ctlp_QuantifierFree_c;
2649  case Ctlp_Cmp_c:
2650    return Ctlp_Mixed_c;
2651  default:
2652    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
2653    assert(0);
2654    return Ctlp_Mixed_c;
2655  }
2656} /* End of Ctlp_CheckTypeOfExistentialFormula */
2657
2658/**Function********************************************************************
2659
2660  Synopsis [Tests if an array of simple existential formulae has only
2661  ACTL, only ECTL or mixture of formula.]
2662
2663  Description        [Returns Ctlp_ECTL_c if the array contains only
2664  ECTL formulae, Ctlp_ACTL_c if it contains only ACTL formulae,
2665  Ctlp_QuantifierFree_c if there are no quantifiers in any formulae,
2666  and Ctlp_Mixed otherwise.]
2667
2668  SideEffects        []
2669
2670  SeeAlso            [Ctlp_CheckClassOfExistentialFormula]
2671
2672******************************************************************************/
2673Ctlp_FormulaClass
2674Ctlp_CheckClassOfExistentialFormulaArray(
2675  array_t *formulaArray)
2676{
2677  Ctlp_FormulaClass result;
2678  Ctlp_Formula_t *formula;
2679  int formulanr;
2680
2681  result = Ctlp_QuantifierFree_c;
2682  arrayForEachItem(Ctlp_Formula_t *, formulaArray, formulanr, formula){
2683    Ctlp_FormulaClass  formulaType;
2684    formulaType = Ctlp_CheckClassOfExistentialFormula(formula);
2685    result = CtlpResolveClass(result, formulaType);
2686    if(result == Ctlp_Mixed_c)
2687      return result;
2688  }
2689  return result;
2690} /* End of Ctlp_CheckTypeOfExistentialFormulaArray */
2691
2692
2693/**Function********************************************************************
2694
2695  Synopsis    [Compare two formulas for equality]
2696
2697  Description [Checks if two formulas are syntactically the same.  Equivalent
2698  constructions such as TRUE and TRUE+FALSE are not recognized, but copies are
2699  handled correctly, and strings are compared using strcmp.]
2700
2701  SideEffects []
2702
2703  SeeAlso     [FormulaCompare]
2704
2705******************************************************************************/
2706boolean
2707Ctlp_FormulaIdentical(
2708  Ctlp_Formula_t *formula1,
2709  Ctlp_Formula_t *formula2)
2710{
2711  return(FormulaCompare((char *)formula1, (char *)formula2) == 0);
2712}
2713
2714
2715/**Function********************************************************************
2716
2717  Synopsis    [Replaces non-monotonic operators in a formula.]
2718
2719  Description [This function takes a parse tree for a CTL formula and
2720  transforms it into another tree that has only monotonic operators.
2721  The non-monotonic operators are <code>XOR</code> and <code>EQ</code>.
2722  They are replaced by eqivalent trees.  Specificallt, <code>XOR(a,b)</code>
2723  is replaced by <code>OR(AND(a,NOT(b)),AND(NOT(a),b))</code> and
2724  <code>f <-> g</code> is replaced by <code>AND(f->g,g->f)</code>.<p>
2725
2726  It is important that the original formula be a tree.  The idea is that this
2727  function should be called right after reading the formulae from file.  Since
2728  the information attached to the parse tree by the model checking procedures
2729  is not preserved, it is also important that no such information exists.
2730  These conditions are checked by an assertion.<p>
2731
2732  This function does not deal with the forward CTL operators.  Reduction to
2733  monotonic operators should be performed before conversion to forward CTL.]
2734
2735  SideEffects [The argument is modified.  The new formulae will apprear
2736  when they are printed out.]
2737
2738  SeeAlso     [Ctlp_FormulaArrayMakeMonotonic]
2739
2740******************************************************************************/
2741void
2742Ctlp_FormulaMakeMonotonic(
2743  Ctlp_Formula_t *formula)
2744{
2745  Ctlp_Formula_t *left, *right;
2746  Ctlp_FormulaType type;
2747
2748  if (formula == NIL(Ctlp_Formula_t)) {
2749    return;
2750  }
2751
2752  /* Make sure (recursively) that this (sub)-formula is still in its pristine
2753   * state.  Specifically, that the parse graph is a tree.
2754   */
2755  assert(formula->refCount == 1 &&
2756         formula->states == NIL(mdd_t) &&
2757         formula->underapprox == NIL(mdd_t) &&
2758         formula->overapprox == NIL(mdd_t) &&
2759         formula->latest == Ctlp_Incomparable_c &&
2760         formula->dbgInfo.data == NIL(void) &&
2761         formula->dbgInfo.freeFn == (Ctlp_DbgInfoFreeFn) NULL &&
2762         formula->dbgInfo.convertedFlag == FALSE &&
2763         formula->dbgInfo.originalFormula == NIL(Ctlp_Formula_t) &&
2764         formula->top == 0 &&
2765         formula->compareValue == 0
2766         );
2767
2768  type = Ctlp_FormulaReadType(formula);
2769
2770  /* Leaves remain unchanged. */
2771  if (type == Ctlp_ID_c || type == Ctlp_TRUE_c || type == Ctlp_FALSE_c) {
2772    return;
2773  }
2774
2775  /* First recursively fix the children. */
2776  left  = Ctlp_FormulaReadLeftChild(formula);
2777  Ctlp_FormulaMakeMonotonic(left);
2778  right = Ctlp_FormulaReadRightChild(formula);
2779  Ctlp_FormulaMakeMonotonic(right);
2780
2781  /* Fix this node if it is not monotonic. */
2782  switch (type) {
2783  case Ctlp_EX_c:
2784  case Ctlp_EG_c:
2785  case Ctlp_EF_c:
2786  case Ctlp_EU_c:
2787  case Ctlp_AX_c:
2788  case Ctlp_AG_c:
2789  case Ctlp_AF_c:
2790  case Ctlp_AU_c:
2791  case Ctlp_OR_c:
2792  case Ctlp_AND_c:
2793  case Ctlp_NOT_c:
2794  case Ctlp_THEN_c:
2795  case Ctlp_EY_c:
2796  case Ctlp_EH_c:
2797    /* Nothing to be done */
2798    break;
2799  case Ctlp_EQ_c: {
2800    Ctlp_Formula_t *dupLeft, *dupRight;
2801    Ctlp_Formula_t *thenLeft, *thenRight;
2802    dupLeft   = Ctlp_FormulaDup(left);
2803    dupRight  = Ctlp_FormulaDup(right);
2804    thenLeft  = Ctlp_FormulaCreate(Ctlp_THEN_c, left, right);
2805    thenRight = Ctlp_FormulaCreate(Ctlp_THEN_c, dupRight, dupLeft);
2806    /* Fix the node in place. */
2807    formula->type  = Ctlp_AND_c;
2808    formula->left  = thenLeft;
2809    formula->right = thenRight;
2810    break;
2811  }
2812  case Ctlp_XOR_c: {
2813    Ctlp_Formula_t *dupLeft, *dupRight;
2814    Ctlp_Formula_t *negLeft, *negRight;
2815    Ctlp_Formula_t *andLeft, *andRight;
2816    dupLeft  = Ctlp_FormulaDup(left);
2817    dupRight = Ctlp_FormulaDup(right);
2818    negLeft  = Ctlp_FormulaCreate(Ctlp_NOT_c, dupLeft, NIL(Ctlp_Formula_t));
2819    negRight = Ctlp_FormulaCreate(Ctlp_NOT_c, dupRight, NIL(Ctlp_Formula_t));
2820    andLeft  = Ctlp_FormulaCreate(Ctlp_AND_c, left, negRight);
2821    andRight = Ctlp_FormulaCreate(Ctlp_AND_c, negLeft, right);
2822    /* Fix the node in place. */
2823    formula->type  = Ctlp_OR_c;
2824    formula->left  = andLeft;
2825    formula->right = andRight;
2826    break;
2827  }
2828  default:
2829    /* Forward CTL operators (that are not supported) and leaves (that are
2830     * dealt with above) would fall here.
2831     */
2832    fail("unexpected CTL formula type\n");
2833  }
2834
2835  return;
2836
2837} /* Ctlp_FormulaMakeMonotonic */
2838
2839
2840/**Function********************************************************************
2841
2842  Synopsis    [Replaces non-monotonic operators in an array of formulae.]
2843
2844  Description [Apply Ctlp_FormulaMakeMonotonic to each formula in the array.]
2845
2846  SideEffects [The formulae in the array are modified.]
2847
2848  SeeAlso     [Ctlp_FormulaMakeMonotonic]
2849
2850******************************************************************************/
2851void
2852Ctlp_FormulaArrayMakeMonotonic(
2853  array_t *formulaArray /* of Ctlp_Formula_t */)
2854{
2855  int i;
2856  Ctlp_Formula_t *formula;
2857
2858  if (formulaArray == NIL(array_t)) return;
2859  arrayForEachItem(Ctlp_Formula_t *, formulaArray, i, formula) {
2860    Ctlp_FormulaMakeMonotonic(formula);
2861  }
2862
2863} /* Ctlp_FormulaArrayMakeMonotonic */
2864
2865
2866/*---------------------------------------------------------------------------*/
2867/* Definition of internal functions                                          */
2868/*---------------------------------------------------------------------------*/
2869
2870
2871/**Function********************************************************************
2872
2873  Synopsis    [Increments the reference count of a formula.]
2874
2875  Description [The function increments the reference count of a formula. If
2876  the formula is NULL, the function does nothing.]
2877
2878  SideEffects []
2879
2880  SeeAlso     []
2881
2882******************************************************************************/
2883void
2884CtlpFormulaIncrementRefCount(
2885  Ctlp_Formula_t *formula)
2886{
2887  if(formula!=NIL(Ctlp_Formula_t)) {
2888    ++(formula->refCount);
2889  }
2890}
2891
2892/**Function********************************************************************
2893
2894  Synopsis    [Decrements the reference count of a formula.]
2895
2896  Description [The function decrements the reference count of formula and if
2897  the reference count reaches 0, the formula is freed. If the formula is NULL,
2898  the function does nothing. It is an error to decrement the reference count
2899  below 0.]
2900
2901  SideEffects []
2902
2903  SeeAlso     []
2904
2905******************************************************************************/
2906void
2907CtlpFormulaDecrementRefCount(
2908  Ctlp_Formula_t *formula)
2909{
2910  if(formula!=NIL(Ctlp_Formula_t)) {
2911    assert(formula->refCount>0);
2912    if(--(formula->refCount) == 0)
2913      CtlpFormulaFree(formula);
2914  }
2915}
2916/**Function********************************************************************
2917
2918  Synopsis    [Adds formula to the end of globalFormulaArray.]
2919
2920  SideEffects [Manipulates the global variable globalFormulaArray.]
2921
2922  SeeAlso     [CtlpYyparse]
2923
2924******************************************************************************/
2925void
2926CtlpFormulaAddToGlobalArray(
2927  Ctlp_Formula_t * formula)
2928{
2929  array_insert_last(Ctlp_Formula_t *, globalFormulaArray, formula);
2930}
2931
2932/**Function********************************************************************
2933
2934  Synopsis    [Frees a CTL formula.]
2935
2936  Description [The function frees all memory associated with the formula,
2937  including all MDDs and all character strings (however, does not free
2938  dbgInfo.originalFormula). It also decrements the reference counts of its two
2939  chidren. The function does nothing if formula is NULL.]
2940
2941  SideEffects []
2942
2943  SeeAlso     [Ctlp_FormulaArrayFree]
2944
2945******************************************************************************/
2946void
2947CtlpFormulaFree(
2948  Ctlp_Formula_t * formula)
2949{
2950  if (formula != NIL(Ctlp_Formula_t)) {
2951
2952    /*
2953     * Free any fields that are not NULL.
2954     */
2955
2956    if (formula->type == Ctlp_ID_c) {
2957      FREE(formula->left);
2958      FREE(formula->right);
2959    }
2960    else {
2961      if (formula->left  != NIL(Ctlp_Formula_t)) {
2962        CtlpFormulaDecrementRefCount(formula->left);
2963      }
2964      if (formula->right != NIL(Ctlp_Formula_t)) {
2965        CtlpFormulaDecrementRefCount(formula->right);
2966      }
2967    }
2968    if (formula->states != NIL(mdd_t))
2969      mdd_free(formula->states);
2970    if (formula->underapprox != NIL(mdd_t))
2971      mdd_free(formula->underapprox);
2972    if (formula->overapprox != NIL(mdd_t))
2973      mdd_free(formula->overapprox);
2974    if (formula->Bottomstates != NIL(array_t))
2975      mdd_array_free(formula->Bottomstates);
2976    if (formula->Topstates != NIL(array_t))
2977      mdd_array_free(formula->Topstates);
2978    if (formula->matchfound_top != NIL(array_t))
2979      array_free(formula->matchfound_top);
2980    if (formula->matchelement_top != NIL(array_t))
2981      array_free(formula->matchelement_top);
2982    if (formula->matchfound_bot != NIL(array_t))
2983      array_free(formula->matchfound_bot);
2984    if (formula->matchelement_bot != NIL(array_t))
2985      array_free(formula->matchelement_bot);
2986    if (formula->leaves != NIL(array_t))
2987      array_free(formula->leaves);
2988    if (formula->dbgInfo.data != NIL(void)) {
2989      (*formula->dbgInfo.freeFn)(formula);
2990    }
2991    FREE(formula);
2992  }
2993}
2994
2995
2996/**Function********************************************************************
2997
2998  Synopsis    [Create a binary string of given value with size of interval ]
2999
3000  Description [The value is a binary string starting with 'b',
3001  a hexadecimal string starting with 'x', or an
3002  integer string. If Value is not fitted in the interval, 0 is return.
3003  Otherwise 1 is returned. Result string is saved at given pointer.]
3004
3005  SideEffects []
3006
3007  SeeAlso     []
3008
3009******************************************************************************/
3010int
3011CtlpStringChangeValueStrToBinString(
3012  char *value,
3013  char *binValueStr,
3014  int  interval)
3015{
3016  int i;
3017  long int num, mask;
3018  double maxNum;
3019  char *ptr;
3020
3021  mask = 1;
3022  maxNum = pow(2.0,(double)interval);
3023  errno = 0;
3024
3025  if(value[0] == 'b'){
3026    if ((int)strlen(value)-1 == interval){
3027                        for(i=1;i<=interval;i++){
3028        if (value[i] == '0' || value[i] == '1'){
3029          binValueStr[i-1] =  value[i];
3030        }else{
3031          return 0;
3032        }
3033      }
3034      binValueStr[interval] = '\0';
3035    }else{
3036      return 0;
3037    }
3038  }else if (value[0] == 'x'){
3039    for(i=1; i < (int)strlen(value); i++){
3040      if (!isxdigit((int)value[i])){
3041        return 0;
3042      }
3043    }
3044    num = strtol(++value,&ptr,16);
3045    if (errno) return 0;
3046    if ( num >= maxNum) return 0;
3047    for(i=0;i<interval;i++){
3048      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
3049      else binValueStr[interval-i-1] = '0';
3050    }
3051    binValueStr[interval] = '\0';
3052  }else{
3053    for(i=0;i<(int)strlen(value);i++){
3054      if (!isdigit((int)value[i])){
3055        return 0;
3056      }
3057    }
3058    num = strtol(value,&ptr,0);
3059    if (errno) return 0;
3060    if ( num >= maxNum) return 0;
3061    mask = 1;
3062    for(i=0;i<interval;i++){
3063      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
3064      else binValueStr[interval-i-1] = '0';
3065    }
3066    binValueStr[interval] = '\0';
3067  }
3068
3069  return(1);
3070}
3071
3072
3073/**Function********************************************************************
3074
3075  Synopsis    [Change [] to <>]
3076
3077  Description []
3078
3079  SideEffects [The input string contains ...[num] and this function changes it
3080  to ...<num>.]
3081
3082  SeeAlso     []
3083
3084******************************************************************************/
3085void
3086CtlpChangeBracket(
3087  char *inStr)
3088{
3089  int i, j;
3090  char *str;
3091
3092  j = 0;
3093  for (i=0;i<(int)strlen(inStr)+1;i++){
3094    if (inStr[i] != ' '){
3095      inStr[i-j] = inStr[i];
3096    }else{
3097      j++;
3098    }
3099  }
3100
3101  if (changeBracket == 0)
3102    return;
3103
3104  str = strchr(inStr,'[');
3105  if (str == NULL) return;
3106
3107  *str = '<';
3108  str = strchr(inStr,']');
3109  *str = '>';
3110}
3111
3112
3113/**Function********************************************************************
3114
3115  Synopsis    [Parse a given vector string.]
3116
3117  Description [Parse given vector string of the form of var<i:j> and
3118  string var is returned. Other information such as i, j, interval between
3119  i and j, and increment or decrement from i to j are saved.]
3120
3121  SideEffects []
3122
3123  SeeAlso     []
3124
3125******************************************************************************/
3126char *
3127CtlpGetVectorInfoFromStr(
3128   char *str,
3129   int  *start,
3130   int  *end,
3131   int  *interval,
3132   int  *inc)
3133{
3134  char *str1, *str2, *str3;
3135  char *startStr, *endStr;
3136  char *name, *ptr;
3137
3138  str1 = strchr(str,'[');
3139  str2 = strchr(str,':');
3140  str3 = strchr(str,']');
3141  startStr = ALLOC(char, str2-str1);
3142  endStr = ALLOC(char, str3-str2);
3143  name = ALLOC(char, str1-str+1);
3144
3145  (void) strncpy(name, str, str1-str);
3146  (void) strncpy(startStr, str1+1, str2-str1-1);
3147  (void) strncpy(endStr, str2+1, str3-str2-1);
3148
3149  startStr[str2-str1-1] = '\0';
3150  endStr[str3-str2-1] = '\0';
3151  name[str1-str] = '\0';
3152  *start = strtol(startStr,&ptr,0);
3153  *end = strtol(endStr,&ptr,0);
3154  if(*start > *end){
3155      *inc = -1;
3156      *interval = *start - *end + 1;
3157  } else {
3158      *inc = 1;
3159      *interval = *end - *start + 1;
3160  }
3161  FREE(startStr);
3162  FREE(endStr);
3163  return name;
3164}
3165
3166/**Function********************************************************************
3167
3168  Synopsis    [Insert macro formula into symbol table.]
3169
3170  Description [If the name is already in table return 0, otherwise insert the
3171  formula into the table and return 1]
3172
3173  SideEffects []
3174
3175  SeeAlso     []
3176
3177******************************************************************************/
3178int
3179CtlpFormulaAddToTable(
3180   char *name,
3181   Ctlp_Formula_t *formula,
3182   st_table *macroTable)
3183{
3184   if(macroTable == NIL(st_table)){
3185      macroTable = st_init_table(strcmp, st_strhash);
3186   }
3187   if(st_is_member(macroTable, name)){
3188      return 0;
3189   }
3190   st_insert(macroTable, name, (char *)formula);
3191   return 1;
3192}
3193
3194
3195/**Function********************************************************************
3196
3197  Synopsis    [Get macro formula from symbol table]
3198
3199  Description [If macro string is not found in table, NULL pointer is returned]
3200
3201  SideEffects []
3202
3203  SeeAlso     []
3204
3205******************************************************************************/
3206Ctlp_Formula_t *
3207CtlpFormulaFindInTable(
3208   char *name,
3209   st_table *macroTable)
3210{
3211   Ctlp_Formula_t *formula;
3212   if (st_lookup(macroTable, name, &formula)){
3213      return (Ctlp_FormulaDup(formula));
3214   }else{
3215      return NIL(Ctlp_Formula_t);
3216   }
3217}
3218
3219/**Function********************************************************************
3220
3221  Synopsis    [Returns the greatest lower bound of two classes]
3222
3223  Description [Returns the class of a formula that is the combination of a
3224  formula of class1 and class2.  Does this by computing the glb, where mixed <
3225  ECTL < quantifierFree, and mixed < ACTL < quantifierfree.]
3226
3227  SideEffects []
3228
3229  SeeAlso [Ctlp_CheckClassOfExistentialFormula]
3230
3231******************************************************************************/
3232Ctlp_FormulaClass
3233CtlpResolveClass(
3234  Ctlp_FormulaClass class1,
3235  Ctlp_FormulaClass class2)
3236{
3237  if ((class1 == Ctlp_Mixed_c) || (class2 == Ctlp_Mixed_c))
3238    return Ctlp_Mixed_c;
3239  if (class1 == Ctlp_QuantifierFree_c)
3240    return class2;
3241  if (class2 == Ctlp_QuantifierFree_c)
3242    return class1;
3243  if (class1 == class2)
3244    return class1;
3245
3246  return Ctlp_Mixed_c;
3247
3248}
3249
3250
3251/**Function********************************************************************
3252
3253  Synopsis    [Returns the class of a formula that is the negation of a formula
3254  of class "class".]
3255
3256  Description [The negation of a mixed (quantifier free, ECTL, ACTL) formula is
3257  mixed (quantifier free, ACTL, ECTL).]
3258
3259  SideEffects []
3260
3261  SeeAlso [Ctlp_CheckClassOfExistentialFormula]
3262
3263******************************************************************************/
3264Ctlp_FormulaClass
3265CtlpNegateFormulaClass(
3266  Ctlp_FormulaClass class_
3267)
3268{
3269  switch(class_){
3270  case Ctlp_Mixed_c:
3271    return Ctlp_Mixed_c;
3272  case Ctlp_QuantifierFree_c:
3273    return Ctlp_QuantifierFree_c;
3274  case Ctlp_ECTL_c:
3275    return Ctlp_ACTL_c;
3276  case Ctlp_ACTL_c:
3277    return Ctlp_ECTL_c;
3278  default:
3279    fprintf(vis_stderr, "**Ctlp Error: Unknown formula class\n");
3280    assert(0);
3281    return Ctlp_Mixed_c;
3282  }
3283}
3284
3285
3286/**Function********************************************************************
3287
3288  Synopsis    [Replaces the smallest important sub-fomula in a w-ACTL
3289  formula by bottom.]
3290
3291  Description [Creates a witness formula for a given w-ACTL formula by
3292  replacing the smallest inpurtant subformula with bottom.  This function is
3293  used in the approach to vacuity detection of Beer et al. (CAV97).  Formulae
3294  in w-ACTL are guaranteed to have a unique smallest important subformula,
3295  which is defined as follow.  If the formula is simple, its operands are not
3296  important.  (An exception is made for implications.  See
3297  ReplaceSimpleFormula.)  Otherwise, the non-simple operand is the important
3298  operand.  For (A p U q) or (E p U q), where p and q are both simple, p is the
3299  important operand.  For unary formulae, the only child is the important
3300  operand.  This function works also for ACTL formulae that are not in w-ACTL,
3301  and for which smallest important subformulae are not unique.
3302  The function picks up a smallest important subformula.]
3303
3304  SideEffects [none]
3305
3306  SeeAlso     [ReplaceSimpleFormula]
3307
3308******************************************************************************/
3309Ctlp_Formula_t *
3310Ctlp_FormulaCreateWitnessFormula(
3311  Ctlp_Formula_t *formula)
3312{
3313  Ctlp_FormulaType formulaType;
3314  Ctlp_Formula_t *rightFormula, *leftFormula;
3315  Ctlp_Formula_t *newLeftFormula, *newRightFormula;
3316
3317  assert(formula != NIL(Ctlp_Formula_t));
3318
3319  if(formula == NIL(Ctlp_Formula_t))
3320    return NIL(Ctlp_Formula_t);
3321
3322  formulaType = Ctlp_FormulaReadType(formula);
3323  leftFormula = Ctlp_FormulaReadLeftChild(formula);
3324  rightFormula = Ctlp_FormulaReadRightChild(formula);
3325
3326  if (Ctlp_FormulaTestIsQuantifierFree(formula)) {
3327    return ReplaceSimpleFormula(formula);
3328  }
3329
3330  switch (formulaType) {
3331  case Ctlp_AX_c:
3332  case Ctlp_EX_c:
3333  case Ctlp_AG_c:
3334  case Ctlp_EG_c:
3335  case Ctlp_AF_c:
3336  case Ctlp_EF_c:
3337  case Ctlp_NOT_c:
3338    newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
3339    newRightFormula = NIL(Ctlp_Formula_t);
3340    break;
3341  case Ctlp_AU_c:
3342  case Ctlp_EU_c:
3343    /* If both or neither operands are simple, we choose the left one
3344       as important.  Deal with special case of converted AG p (E true U p). */
3345    if ((formulaType == Ctlp_EU_c &&
3346         Ctlp_FormulaReadType(leftFormula) == Ctlp_TRUE_c) ||
3347        (Ctlp_FormulaTestIsQuantifierFree(leftFormula) &&
3348         !Ctlp_FormulaTestIsQuantifierFree(rightFormula))) {
3349      newLeftFormula = Ctlp_FormulaDup(leftFormula);
3350      newRightFormula = Ctlp_FormulaCreateWitnessFormula(rightFormula);
3351    } else {
3352      newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
3353      newRightFormula = Ctlp_FormulaDup(rightFormula);
3354    }
3355    break;
3356  case Ctlp_OR_c:
3357  case Ctlp_AND_c:
3358  case Ctlp_THEN_c:
3359    /* Here we know one is not simple */
3360    if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) {
3361      newLeftFormula = Ctlp_FormulaDup(leftFormula);
3362      newRightFormula = Ctlp_FormulaCreateWitnessFormula(rightFormula);
3363    } else {
3364      newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
3365      newRightFormula = Ctlp_FormulaDup(rightFormula);
3366    }
3367    break;
3368  case Ctlp_XOR_c:
3369  case Ctlp_EQ_c:
3370    newLeftFormula = Ctlp_FormulaDup(leftFormula);
3371    newRightFormula = Ctlp_FormulaDup(rightFormula);
3372    break;
3373  default:
3374    newLeftFormula = NIL(Ctlp_Formula_t);
3375    newRightFormula = NIL(Ctlp_Formula_t);
3376    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
3377    assert(0);
3378    break;
3379  }
3380  return Ctlp_FormulaCreate(formulaType,newLeftFormula,newRightFormula);
3381
3382} /* Ctlp_FormulaCreateWitnessFormula */
3383
3384
3385/*---------------------------------------------------------------------------*/
3386/* Definition of static functions                                            */
3387/*---------------------------------------------------------------------------*/
3388
3389/**Function********************************************************************
3390
3391  Synopsis    [Creates a CTL formula with just the type set.]
3392
3393  Description [Calls Ctlp_FormulaCreate with type, and all other fields NULL.]
3394
3395  SideEffects []
3396
3397  SeeAlso     [Ctlp_FormulaCreate]
3398
3399******************************************************************************/
3400static Ctlp_Formula_t *
3401FormulaCreateWithType(
3402  Ctlp_FormulaType  type)
3403{
3404  return (Ctlp_FormulaCreate(type, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t)));
3405}
3406
3407
3408/**Function********************************************************************
3409
3410  Synopsis    [The comparison function for the formula unique table.]
3411
3412  Description [The function takes as parameters two CTL formulae. It compares
3413  the formula type, the left child and the right child, and returns 0 if they
3414  match. Otherwise, it returns -1.]
3415
3416  SideEffects []
3417
3418  SeeAlso     [FormulaHash]
3419
3420******************************************************************************/
3421static int
3422FormulaCompare(
3423  const char *key1,
3424  const char *key2)
3425{
3426  Ctlp_Formula_t *formula1 = (Ctlp_Formula_t *) key1;
3427  Ctlp_Formula_t *formula2 = (Ctlp_Formula_t *) key2;
3428
3429  assert(key1 != NIL(char));
3430  assert(key2 != NIL(char));
3431
3432
3433  if(formula1->type != formula2->type) {
3434    return -1;
3435  }
3436  if(formula1->type == Ctlp_ID_c) {
3437    if(strcmp((char *) (formula1->left), (char *) (formula2->left)) ||
3438       strcmp((char *) (formula1->right), (char *) (formula2->right))) {
3439      return -1;
3440    } else
3441      return 0;
3442  } else {
3443    if(formula1->left != formula2->left)
3444      return -1;
3445    if(formula1->right != formula2->right)
3446      return -1;
3447    if (formula1->type == Ctlp_Cmp_c &&
3448        formula1->compareValue != formula2->compareValue) {
3449      return -1;
3450    }
3451    return 0;
3452  }
3453}
3454
3455/**Function********************************************************************
3456
3457  Synopsis    [The hash function for the formula unique table.]
3458
3459  Description [The function takes as parameter a CTL formula. If the formula
3460  type is Ctlp_ID_c, st_strhash is used with a concatenation of left and
3461  right children as the key string. Otherwise, something very similar to
3462  st_ptrhash is done.]
3463
3464  SideEffects []
3465
3466  SeeAlso     [FormulaCompare]
3467
3468******************************************************************************/
3469static int
3470FormulaHash(
3471  char *key,
3472  int modulus)
3473{
3474  char *hashString;
3475  int hashValue;
3476  Ctlp_Formula_t *formula = (Ctlp_Formula_t *) key;
3477
3478  if(formula->type==Ctlp_ID_c) {
3479    hashString = util_strcat3((char *) (formula->left), (char *)
3480                              (formula->right), "");
3481    hashValue = st_strhash(hashString, modulus);
3482    FREE(hashString);
3483    return hashValue;
3484  }
3485  return (int) ((((unsigned long) formula->left >>2) +
3486                 ((unsigned long) formula->right >>2)) % modulus);
3487}
3488
3489/**Function********************************************************************
3490
3491  Synopsis    [Hashes the formula into the unique table.]
3492
3493  Description [The function takes a formula and hashes it and all its
3494  subformulae into a unique table. It returns the unique formula identical to
3495  the formula being hashed. The formula returned will have maximum sharing
3496  with the formulae that are already present in uniqueTable. It returns
3497  NIL(Ctlp_Formula_t) if the formula is NIL(Ctlp_Formula_t).]
3498
3499  SideEffects [If a copy of some subformula of formula is present in
3500  uniqueTable then the copy is substituted for it and the reference count of
3501  the subform
3502  ula is decremented.]
3503
3504  SeeAlso     [FormulaCompare]
3505
3506******************************************************************************/
3507static Ctlp_Formula_t *
3508FormulaHashIntoUniqueTable(
3509  Ctlp_Formula_t *formula,
3510  st_table *uniqueTable)
3511{
3512  Ctlp_Formula_t *uniqueFormula, *uniqueLeft, *uniqueRight;
3513
3514  if(formula == NIL(Ctlp_Formula_t))
3515    return NIL(Ctlp_Formula_t);
3516  if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
3517    return uniqueFormula;
3518  }
3519  else {
3520    if(formula->type == Ctlp_ID_c) {
3521      st_insert(uniqueTable, formula, formula);
3522      return formula;
3523    }
3524    else {
3525      uniqueLeft = FormulaHashIntoUniqueTable(formula->left, uniqueTable);
3526      if(uniqueLeft != NIL(Ctlp_Formula_t))
3527        if(uniqueLeft != formula->left) {
3528          CtlpFormulaDecrementRefCount(formula->left);
3529          formula->left = uniqueLeft;
3530          CtlpFormulaIncrementRefCount(formula->left);
3531        }
3532      uniqueRight = FormulaHashIntoUniqueTable(formula->right, uniqueTable);
3533      if(uniqueRight != NIL(Ctlp_Formula_t))
3534        if(uniqueRight != formula->right) {
3535          CtlpFormulaDecrementRefCount(formula->right);
3536          formula->right = uniqueRight;
3537          CtlpFormulaIncrementRefCount(formula->right);
3538        }
3539      if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
3540        return uniqueFormula;
3541      }
3542      else {
3543        st_insert(uniqueTable, formula, formula);
3544        return formula;
3545      }
3546    }
3547  }
3548}
3549
3550/**Function********************************************************************
3551
3552  Synopsis    [Converts the formula tree to a DAG.]
3553
3554  Description [The function recursively builds an existential DAG for the
3555  formula. If a particular sub-formula has been encountered before, the
3556  converted existential sub-formula is pointed to by the field states and it
3557  is returned without creating a new formula.]
3558
3559  SideEffects [We abuse states to store which converted formula an original
3560  formula points to.]
3561
3562  SeeAlso     []
3563
3564******************************************************************************/
3565static Ctlp_Formula_t *
3566FormulaConvertToExistentialDAG(
3567  Ctlp_Formula_t *formula)
3568{
3569
3570  Ctlp_Formula_t *new_;
3571  char *variableNameCopy, *valueNameCopy;
3572
3573  if(formula==NIL(Ctlp_Formula_t))
3574    return NIL(Ctlp_Formula_t);
3575
3576  if(formula->states!=NIL(mdd_t)) {
3577    Ctlp_Formula_t *temp = (Ctlp_Formula_t *) (formula->states);
3578
3579    ++(temp->refCount);
3580    return temp;
3581  }
3582
3583  /*
3584   * Recursively convert each subformula.
3585   */
3586
3587  switch(formula->type) {
3588    case Ctlp_EF_c:
3589      /* EFf --> (E true U f)  */
3590      new_ = FormulaCreateWithType(Ctlp_EU_c);
3591      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
3592      new_->right = FormulaConvertToExistentialDAG(formula->left);
3593      new_->dbgInfo.convertedFlag = TRUE;
3594      break;
3595
3596    case Ctlp_AX_c:
3597      /* AXf --> !(EX(!f)) */
3598      new_ = FormulaCreateWithType(Ctlp_NOT_c);
3599      new_->left = FormulaCreateWithType(Ctlp_EX_c);
3600      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
3601      new_->left->left->left = FormulaConvertToExistentialDAG(formula->left);
3602      new_->dbgInfo.convertedFlag = TRUE;
3603      break;
3604
3605    case Ctlp_AG_c:
3606      /* AGf --> ![(E true U !f)] */
3607      new_ = FormulaCreateWithType(Ctlp_NOT_c);
3608      new_->left = FormulaCreateWithType(Ctlp_EU_c);
3609      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
3610      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
3611      new_->left->right->left = FormulaConvertToExistentialDAG(formula->left);
3612      new_->dbgInfo.convertedFlag = TRUE;
3613      break;
3614
3615    case Ctlp_AF_c:
3616      /* AFf --> ![EG(!f)] */
3617      new_ = FormulaCreateWithType(Ctlp_NOT_c);
3618      new_->left = FormulaCreateWithType(Ctlp_EG_c);
3619      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
3620      new_->left->left->left = FormulaConvertToExistentialDAG(formula->left);
3621      new_->dbgInfo.convertedFlag = TRUE;
3622      break;
3623
3624    case Ctlp_AU_c:
3625      /* A[fUg] --> !((E[!g U (!f*!g)]) + (EG!g)) */
3626
3627      new_ = FormulaCreateWithType(Ctlp_NOT_c); /* top */
3628      new_->left = FormulaCreateWithType(Ctlp_OR_c); /* ((E[!g U (!f*!g)]) + (EG!g)) */
3629
3630      new_->left->right = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
3631      new_->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
3632      new_->left->right->left->left = FormulaConvertToExistentialDAG(formula->right); /* g */
3633
3634      new_->left->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
3635      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
3636      new_->left->left->left->left = FormulaConvertToExistentialDAG(formula->right); /* g */
3637      new_->left->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
3638      new_->left->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
3639      new_->left->left->right->left->left = FormulaConvertToExistentialDAG(formula->left); /* f */
3640      new_->left->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
3641      new_->left->left->right->right->left = FormulaConvertToExistentialDAG(formula->right); /* g */
3642      new_->dbgInfo.convertedFlag = TRUE;
3643      break;
3644
3645    case Ctlp_ID_c:
3646      /* Make a copy of the name, and create a new formula. */
3647      variableNameCopy = util_strsav((char *)(formula->left));
3648      valueNameCopy = util_strsav((char *)(formula->right));
3649      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
3650      break;
3651
3652    case Ctlp_THEN_c:
3653    case Ctlp_EX_c:
3654    case Ctlp_EG_c:
3655    case Ctlp_EU_c:
3656    case Ctlp_OR_c:
3657    case Ctlp_AND_c:
3658    case Ctlp_NOT_c:
3659    case Ctlp_XOR_c:
3660    case Ctlp_EQ_c:
3661    case Ctlp_TRUE_c:
3662    case Ctlp_FALSE_c:
3663      /* These are already in the correct form.  Just convert subformulas. */
3664      new_ = FormulaCreateWithType(formula->type);
3665      new_->left = FormulaConvertToExistentialDAG(formula->left);
3666      new_->right = FormulaConvertToExistentialDAG(formula->right);
3667      break;
3668
3669    default:
3670      fail("Unexpected type");
3671  }
3672
3673  formula->states = (mdd_t *) new_; /*using states as pointer to the converted
3674                                     formula */
3675  new_->dbgInfo.originalFormula = formula;
3676  return new_;
3677}
3678
3679
3680/**Function********************************************************************
3681
3682  Synopsis    [Converts an existential formula to forward form.]
3683
3684  Description [Converts an existential formula to forward form. To
3685  convert current formula, it always refer to its parent node and left
3686  child of parent node. Current formula is right child of parent node.
3687  Parent node should be always Ctlp_AND_c and left child of parent node
3688  is already converted.  States is used to store a parent pointer
3689  throughout the procedure.]
3690
3691  SideEffects []
3692
3693  SeeAlso     []
3694
3695******************************************************************************/
3696static void
3697FormulaConvertToForward(Ctlp_Formula_t *formula, int compareValue)
3698{
3699  Ctlp_Formula_t *parent, *save;
3700  Ctlp_Formula_t *p, *q, *r, *f, *g;
3701  int            p_qf, q_qf;
3702  int            same_order;
3703
3704  if (formula == NIL(Ctlp_Formula_t))
3705    return;
3706
3707  parent = (Ctlp_Formula_t *)formula->states;
3708  r = parent->left; /* already converted */
3709
3710  /*
3711   * Recursively convert each subformula.
3712   */
3713
3714  switch(formula->type) {
3715    case Ctlp_EX_c:
3716      /*
3717      ** p ^ EXf -> Img(p) ^ f , Img(p) = EY(p)
3718      **
3719      **   *           *
3720      **  / \         / \
3721      ** p  EX  =>  EY   f
3722      **    |       |
3723      **    f       p
3724      */
3725
3726      formula->type = Ctlp_EY_c;
3727      save = formula->left;
3728      formula->left = parent->left;
3729      parent->left = formula;
3730      parent->right = save;
3731
3732      parent->top = 1;
3733      parent->compareValue = compareValue;
3734      parent->right->states = (mdd_t *)parent;
3735
3736      FormulaConvertToForward(parent->right, compareValue);
3737      break;
3738
3739    case Ctlp_EF_c:
3740      /*
3741      ** EFf --> (E true U f)
3742      ** p ^ (E true U f) --> FwdU(p, true) ^ f
3743      **
3744      **   *             *
3745      **  / \          /   \
3746      ** p  EF  =>  FwdU    f
3747      **    |        / \
3748      **    f       p  true
3749      */
3750
3751      formula->type = Ctlp_FwdU_c;
3752      save = formula->left;
3753      formula->right = FormulaCreateWithType(Ctlp_TRUE_c);
3754      formula->left = parent->left;
3755      parent->left = formula;
3756      parent->right = save;
3757
3758      parent->top = 1;
3759      parent->compareValue = compareValue;
3760      parent->right->states = (mdd_t *)parent;
3761
3762
3763      FormulaConvertToForward(parent->right, compareValue);
3764      break;
3765
3766    case Ctlp_EU_c:
3767      /*
3768      ** p ^ (E q U f) --> FwdU(p, q) ^ f
3769      **
3770      **   *             *
3771      **  / \          /   \
3772      ** p  EU  =>   FwdU   f
3773      **    /\        / \
3774      **   q  f      p   q
3775      */
3776
3777      formula->type = Ctlp_FwdU_c;
3778      save = formula->right;
3779      formula->right = formula->left;
3780      formula->left = parent->left;
3781      parent->left = formula;
3782      parent->right = save;
3783
3784      parent->top = 1;
3785      parent->compareValue = compareValue;
3786      parent->right->states = (mdd_t *)parent;
3787
3788      FormulaConvertToForward(parent->right, compareValue);
3789      break;
3790
3791    case Ctlp_EG_c:
3792      /*
3793      ** p ^ EGq --> FwdG(p, q)
3794      **
3795      **   *        FwdG
3796      **  / \        / \
3797      ** p  EG  =>  p   q
3798      **    /
3799      **   q
3800      */
3801
3802      parent->type = Ctlp_FwdG_c;
3803      parent->right = formula->left;
3804
3805      formula->left = NIL(Ctlp_Formula_t);
3806      formula->states = NIL(mdd_t);
3807      Ctlp_FormulaFree(formula);
3808
3809      parent->top = 1;
3810      parent->compareValue = compareValue;
3811      break;
3812
3813    case Ctlp_NOT_c:
3814      if (formula->left->type == Ctlp_NOT_c) {
3815        /*
3816        **   *             *
3817        **  / \      =>   / \
3818        ** r  NOT        r   f
3819        **     /
3820        **   NOT
3821        **   /
3822        **  f
3823        */
3824
3825        parent->right = formula->left->left;
3826        formula->left->left = NIL(Ctlp_Formula_t);
3827        formula->left->states = NIL(mdd_t);
3828        Ctlp_FormulaFree(formula->left);
3829        formula->left = NIL(Ctlp_Formula_t);
3830        formula->states = NIL(mdd_t);
3831        Ctlp_FormulaFree(formula);
3832
3833        parent->top = 1;
3834        parent->compareValue = compareValue;
3835        parent->right->states = (mdd_t *)parent;
3836
3837        FormulaConvertToForward(parent->right, compareValue);
3838      } else if (formula->left->type == Ctlp_THEN_c) {
3839        /*
3840        **   *
3841        **  / \
3842        ** r  NOT
3843        **    /
3844        **  THEN
3845        **   / \
3846        **  p   q
3847        */
3848
3849        p = formula->left->left;
3850        q = formula->left->right;
3851        p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
3852        q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
3853
3854        if (p_qf && q_qf)
3855          break;
3856        else if (p_qf ||
3857                 (p_qf == 0 && q_qf == 0 && !FormulaIsConvertible(q))) {
3858          /*
3859          ** !(p -> q) = p * !q
3860          **
3861          **   *     =>     *     =>      *
3862          **  / \          / \          /   \
3863          ** r  NOT       r   *        *    NOT
3864          **    /            / \      / \   /
3865          **  THEN          p  NOT   r   p q
3866          **   / \              /
3867          **  p   q            q
3868          */
3869
3870          parent->left = formula->left;
3871          parent->left->type = Ctlp_AND_c;
3872          parent->left->left = r;
3873          parent->left->right = p;
3874          parent->right = formula;
3875          parent->right->left = q;
3876
3877          parent->top = 1;
3878          parent->compareValue = compareValue;
3879          parent->right->states = (mdd_t *)parent;
3880
3881          FormulaConvertToForward(parent->right, compareValue);
3882        } else {
3883          /*
3884          ** !(p -> q) = p * !q
3885          **
3886          **   *     =>     *     =>      *
3887          **  / \          / \          /   \
3888          ** r  NOT       r   *        *     p
3889          **    /            / \      / \
3890          **  THEN          p  NOT   r  NOT
3891          **   / \              /       /
3892          **  p   q            q       q
3893          */
3894
3895          parent->left = formula->left;
3896          parent->left->type = Ctlp_AND_c;
3897          parent->left->left = r;
3898          parent->left->right = formula;
3899          parent->left->right->left = q;
3900          parent->left->right->right = NIL(Ctlp_Formula_t);
3901          parent->right = p;
3902
3903          parent->top = 1;
3904          parent->compareValue = compareValue;
3905          p->states = (mdd_t *)parent;
3906
3907          FormulaConvertToForward(p, compareValue);
3908        }
3909      } else if (formula->left->type == Ctlp_OR_c) {
3910        /*
3911        ** !(p + q) = !p * !q
3912        **
3913        **   *     =>     *     =>        *
3914        **  / \          / \            /   \
3915        ** r  NOT       r   *          *    NOT
3916        **    /            / \        / \    /
3917        **    OR         NOT NOT     r  NOT g=q(p)
3918        **   / \          /   /         /
3919        **  p   q        p   q         f=p(q)
3920        */
3921
3922        p = formula->left->left;
3923        q = formula->left->right;
3924        p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
3925        q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
3926
3927        if (p_qf && q_qf)
3928          break;
3929        else if (p_qf) {
3930          f = p;
3931          g = q;
3932        } else if (q_qf) {
3933          f = q;
3934          g = p;
3935        } else  {
3936          if (!FormulaIsConvertible(q)) {
3937            f = p;
3938            g = q;
3939          } else {
3940            f = q;
3941            g = p;
3942          }
3943        }
3944
3945        parent->left = formula->left;
3946        parent->left->type = Ctlp_AND_c;
3947        parent->left->left = r;
3948        parent->left->right = formula;
3949        parent->left->right->left = f;
3950        parent->left->right->right = NIL(Ctlp_Formula_t);
3951        parent->right = FormulaCreateWithType(Ctlp_NOT_c);
3952        parent->right->left = g;
3953
3954        parent->top = 1;
3955        parent->compareValue = compareValue;
3956        parent->right->states = (mdd_t *)parent;
3957
3958        FormulaConvertToForward(parent->right, compareValue);
3959      } else if (formula->left->type == Ctlp_AND_c) {
3960        /*
3961        ** !(p * q) = !p + !q
3962        **
3963        **   *          *(+)           *(+)
3964        **  / \         / \           /    \
3965        ** r  NOT  =>  r  OR    =>   *      *
3966        **    /           / \       / \    / \
3967        **   AND        NOT NOT    r  NOT r  NOT
3968        **   / \        /   /         /      /
3969        **  p   q      p   q         p      q
3970        */
3971
3972        p = formula->left->left;
3973        q = formula->left->right;
3974
3975        if (Ctlp_FormulaTestIsQuantifierFree(p) &&
3976            Ctlp_FormulaTestIsQuantifierFree(q)) {
3977          break;
3978        }
3979
3980        if (compareValue)
3981          parent->type = Ctlp_OR_c;
3982        parent->left = formula->left;
3983        parent->left->left = r;
3984        parent->left->right = formula;
3985        parent->left->right->left = p;
3986
3987        parent->right = FormulaCreateWithType(Ctlp_AND_c);
3988        parent->right->left = Ctlp_FormulaDup(r);
3989        parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
3990        parent->right->right->left = q;
3991
3992        parent->top = 0;
3993        parent->left->top = 1;
3994        parent->right->top = 1;
3995        parent->left->compareValue = compareValue;
3996        parent->right->compareValue = compareValue;
3997        parent->left->right->states = (mdd_t *)parent->left;
3998        parent->right->right->states = (mdd_t *)parent->right;
3999
4000        FormulaConvertToForward(parent->left->right, compareValue);
4001        FormulaConvertToForward(parent->right->right, compareValue);
4002      } else if (formula->left->type == Ctlp_XOR_c) {
4003        /*
4004        ** !(p ^ q) = p * q + !p * !q
4005        **
4006        **   *              *(+)                   *(+)
4007        **  / \            /     \               /      \
4008        ** |   |   =>     *       *      =>    *          *
4009        ** |   |         / \     / \          / \      /     \
4010        ** r  NOT       r   *   r   *        *   g    *      NOT
4011        **    /            / \     / \      / \      / \     /
4012        **   XOR          p   q  NOT NOT   r   f    r  NOT  g=q(p)
4013        **   / \                 /   /                 /
4014        **  p   q               p   q                 f=p(q)
4015        */
4016
4017        p = formula->left->left;
4018        q = formula->left->right;
4019        p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
4020        q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
4021
4022        same_order = 1;
4023        if (p_qf && q_qf)
4024          break;
4025        else if (p_qf) {
4026          f = p;
4027          g = q;
4028        } else if (q_qf) {
4029          f = q;
4030          g = p;
4031        } else {
4032          if (FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
4033            /*
4034            ** !(p ^ q) = q * p + !p * !q
4035            **
4036            **   *              *(+)                   *(+)
4037            **  / \            /     \               /      \
4038            ** |   |   =>     *       *      =>    *          *
4039            ** |   |         / \     / \          / \      /     \
4040            ** r  NOT       r   *   r   *        *   p    *      NOT
4041            **    /            / \     / \      / \      / \     /
4042            **   XOR          p   q  NOT NOT   r   q    r  NOT  q
4043            **   / \                 /   /                 /
4044            **  p   q               p   q                 p
4045            */
4046
4047            f = q;
4048            g = p;
4049            same_order = 0;
4050          } else if (!FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
4051            /*
4052            ** !(p ^ q) = p * q + !q * !p
4053            **
4054            **   *              *(+)                   *(+)
4055            **  / \            /     \               /      \
4056            ** |   |   =>     *       *      =>    *          *
4057            ** |   |         / \     / \          / \      /     \
4058            ** r  NOT       r   *   r   *        *   q    *      NOT
4059            **    /            / \     / \      / \      / \     /
4060            **   XOR          p   q  NOT NOT   r   p    r  NOT  p
4061            **   / \                 /   /                 /
4062            **  p   q               p   q                 q
4063            */
4064
4065            f = p;
4066            g = q;
4067            same_order = 0;
4068          } else {
4069            f = p;
4070            g = q;
4071          }
4072        }
4073
4074        if (compareValue)
4075          parent->type = Ctlp_OR_c;
4076        parent->left = formula;
4077        parent->left->type = Ctlp_AND_c;
4078        parent->left->left->type = Ctlp_AND_c;
4079        parent->left->left->left = r;
4080        parent->left->left->right = f;
4081        parent->left->right = g;
4082
4083        parent->right = FormulaCreateWithType(Ctlp_AND_c);
4084        parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4085        parent->right->left->left = Ctlp_FormulaDup(r);
4086        parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4087        if (same_order)
4088          parent->right->left->right->left = Ctlp_FormulaDup(f);
4089        else
4090          parent->right->left->right->left = Ctlp_FormulaDup(g);
4091        parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
4092        if (same_order)
4093          parent->right->right->left = Ctlp_FormulaDup(g);
4094        else
4095          parent->right->right->left = Ctlp_FormulaDup(f);
4096
4097        parent->top = 0;
4098        parent->left->top = 1;
4099        parent->right->top = 1;
4100        parent->left->compareValue = compareValue;
4101        parent->right->compareValue = compareValue;
4102        parent->left->right->states = (mdd_t *)parent->left;
4103        parent->right->right->states = (mdd_t *)parent->right;
4104
4105        FormulaConvertToForward(parent->left->right, compareValue);
4106        FormulaConvertToForward(parent->right->right, compareValue);
4107      } else if (formula->left->type == Ctlp_EQ_c) {
4108        /*
4109        ** !(EQ(p, q) = XOR(p, q)
4110        **
4111        **   *              *(+)                   *(+)
4112        **  / \            /     \                /     \
4113        ** |   |   =>     *       *      =>     *         *
4114        ** |   |         / \     / \          /   \     /   \
4115        ** r  NOT       r   *   r   *        *     g   *    NOT
4116        **    /            / \     / \      / \       / \   /
4117        **   EQ           p  NOT NOT  q    r  NOT    r   f g=q(p)
4118        **   / \             /   /            /
4119        **  p   q           q   p            f=p(q)
4120        */
4121
4122        p = formula->left->left;
4123        q = formula->left->right;
4124        p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
4125        q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
4126
4127        if (p_qf && q_qf)
4128          break;
4129        else if (p_qf) {
4130          f = p;
4131          g = q;
4132        } else if (q_qf) {
4133          f = q;
4134          g = p;
4135        } else {
4136          if (FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
4137            /*
4138            ** !(EQ(p, q) = XOR(p, q)
4139            **
4140            **   *              *(+)                   *(+)
4141            **  / \            /     \                /     \
4142            ** |   |   =>     *       *      =>     *         *
4143            ** |   |         / \     / \          /   \     /   \
4144            ** r  NOT       r   *   r   *        *     p   *     q
4145            **    /            / \     / \      / \       / \
4146            **   EQ           p  NOT NOT  q    r  NOT    r  NOT
4147            **   / \             /   /            /         /
4148            **  p   q           q   p            q         p
4149            */
4150
4151            if (compareValue)
4152              parent->type = Ctlp_OR_c;
4153            parent->left = parent->right;
4154            parent->left->type = Ctlp_AND_c;
4155            parent->left->left->type = Ctlp_AND_c;
4156            parent->left->left->left = r;
4157            parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4158            parent->left->left->right->left = q;
4159            parent->left->right = p;
4160
4161            parent->right = FormulaCreateWithType(Ctlp_AND_c);
4162            parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4163            parent->right->left->left = Ctlp_FormulaDup(r);
4164            parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4165            parent->right->left->right->left = Ctlp_FormulaDup(p);
4166            parent->right->right = Ctlp_FormulaDup(q);
4167
4168            parent->top = 0;
4169            parent->left->top = 1;
4170            parent->right->top = 1;
4171            parent->left->compareValue = compareValue;
4172            parent->right->compareValue = compareValue;
4173            parent->left->right->states = (mdd_t *)parent->left;
4174            parent->right->right->states = (mdd_t *)parent->right;
4175
4176            FormulaConvertToForward(parent->left->right, compareValue);
4177            FormulaConvertToForward(parent->right->right, compareValue);
4178            break;
4179          } else if (!FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
4180            /*
4181            ** !(EQ(p, q) = XOR(p, q)
4182            **
4183            **   *              *(+)                   *(+)
4184            **  / \            /     \                /     \
4185            ** |   |   =>     *       *      =>     *         *
4186            ** |   |         / \     / \          /   \     /   \
4187            ** r  NOT       r   *   r   *        *    NOT  *    NOT
4188            **    /            / \     / \      / \   /   / \   /
4189            **   EQ           p  NOT NOT  q    r   p q   r   q p
4190            **   / \             /   /
4191            **  p   q           q   p
4192            */
4193
4194            if (compareValue)
4195              parent->type = Ctlp_OR_c;
4196            parent->left = parent->right;
4197            parent->left->type = Ctlp_AND_c;
4198            parent->left->left->type = Ctlp_AND_c;
4199            parent->left->left->left = r;
4200            parent->left->left->right = p;
4201            parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4202            parent->left->right->left = q;
4203
4204            parent->right = FormulaCreateWithType(Ctlp_AND_c);
4205            parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4206            parent->right->left->left = Ctlp_FormulaDup(r);
4207            parent->right->left->right = Ctlp_FormulaDup(q);
4208            parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
4209            parent->right->right->left = Ctlp_FormulaDup(p);
4210
4211            parent->top = 0;
4212            parent->left->top = 1;
4213            parent->right->top = 1;
4214            parent->left->compareValue = compareValue;
4215            parent->right->compareValue = compareValue;
4216            parent->left->right->states = (mdd_t *)parent->left;
4217            parent->right->right->states = (mdd_t *)parent->right;
4218
4219            FormulaConvertToForward(parent->left->right, compareValue);
4220            FormulaConvertToForward(parent->right->right, compareValue);
4221            break;
4222          } else {
4223            f = p;
4224            g = q;
4225          }
4226        }
4227
4228        if (compareValue)
4229          parent->type = Ctlp_OR_c;
4230        parent->left = parent->right;
4231        parent->left->type = Ctlp_AND_c;
4232        parent->left->left->type = Ctlp_AND_c;
4233        parent->left->left->left = r;
4234        parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4235        parent->left->left->right->left = f;
4236        parent->left->right = g;
4237
4238        parent->right = FormulaCreateWithType(Ctlp_AND_c);
4239        parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4240        parent->right->left->left = Ctlp_FormulaDup(r);
4241        parent->right->left->right = Ctlp_FormulaDup(f);
4242        parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
4243        parent->right->right->left = Ctlp_FormulaDup(g);
4244
4245        parent->top = 0;
4246        parent->left->top = 1;
4247        parent->right->top = 1;
4248        parent->left->compareValue = compareValue;
4249        parent->right->compareValue = compareValue;
4250        parent->left->right->states = (mdd_t *)parent->left;
4251        parent->right->right->states = (mdd_t *)parent->right;
4252
4253        FormulaConvertToForward(parent->left->right, compareValue);
4254        FormulaConvertToForward(parent->right->right, compareValue);
4255      }
4256      break;
4257
4258    case Ctlp_THEN_c:
4259      /*
4260      ** (p -> q) = !p + q
4261      **
4262      **   *              *(+)
4263      **  / \            /    \
4264      ** r THEN  =>     *      *
4265      **    / \        / \    / \
4266      **   p   q      r  NOT r   q
4267      **                 /
4268      **                p
4269      */
4270
4271      p = formula->left;
4272      q = formula->right;
4273
4274      if (Ctlp_FormulaTestIsQuantifierFree(p) &&
4275          Ctlp_FormulaTestIsQuantifierFree(q)) {
4276        break;
4277      }
4278
4279      if (compareValue)
4280        parent->type = Ctlp_OR_c;
4281      parent->left = formula;
4282      parent->left->type = Ctlp_AND_c;
4283      parent->left->left = r;
4284      parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4285      parent->left->right->left = p;
4286
4287      parent->right = FormulaCreateWithType(Ctlp_AND_c);
4288      parent->right->left = Ctlp_FormulaDup(r);
4289      parent->right->right = q;
4290
4291      parent->top = 0;
4292      parent->left->top = 1;
4293      parent->right->top = 1;
4294      parent->left->compareValue = compareValue;
4295      parent->right->compareValue = compareValue;
4296      parent->left->right->states = (mdd_t *)parent->left;
4297      parent->right->right->states = (mdd_t *)parent->right;
4298
4299      FormulaConvertToForward(parent->left->right, compareValue);
4300      FormulaConvertToForward(parent->right->right, compareValue);
4301      break;
4302
4303    case Ctlp_OR_c:
4304      /*
4305      **   *              *(+)
4306      **  / \            /    \
4307      ** r  OR   =>     *      *
4308      **    / \        / \    / \
4309      **   p   q      r   p  r   q
4310      */
4311
4312      p = formula->left;
4313      q = formula->right;
4314
4315      if (Ctlp_FormulaTestIsQuantifierFree(p) &&
4316          Ctlp_FormulaTestIsQuantifierFree(q)) {
4317        break;
4318      }
4319
4320      if (compareValue)
4321        parent->type = Ctlp_OR_c;
4322      parent->left = formula;
4323      parent->left->type = Ctlp_AND_c;
4324      parent->left->left = r;
4325      parent->left->right = p;
4326
4327      parent->right = FormulaCreateWithType(Ctlp_AND_c);
4328      parent->right->left = Ctlp_FormulaDup(r);
4329      parent->right->right = q;
4330
4331      parent->top = 0;
4332      parent->left->top = 1;
4333      parent->right->top = 1;
4334      parent->left->compareValue = compareValue;
4335      parent->right->compareValue = compareValue;
4336      parent->left->right->states = (mdd_t *)parent->left;
4337      parent->right->right->states = (mdd_t *)parent->right;
4338
4339      FormulaConvertToForward(parent->left->right, compareValue);
4340      FormulaConvertToForward(parent->right->right, compareValue);
4341      break;
4342
4343    case Ctlp_AND_c:
4344      /*
4345      **   *     =>     *
4346      **  / \          / \
4347      ** r  AND      AND  g=q(p)
4348      **    / \      / \
4349      **   p   q    r   f=p(q)
4350      */
4351
4352      p = formula->left;
4353      q = formula->right;
4354      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
4355      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
4356
4357      if (p_qf && q_qf)
4358        break;
4359      else if (q_qf) {
4360        f = q;
4361        g = p;
4362      } else {
4363        f = p;
4364        g = q;
4365      }
4366
4367      parent->left = parent->right;
4368      parent->left->left = r;
4369      parent->left->right = f;
4370      parent->right = g;
4371
4372      parent->top = 1;
4373      parent->compareValue = compareValue;
4374      g->states = (mdd_t *)parent;
4375
4376      FormulaConvertToForward(g, compareValue);
4377      break;
4378
4379    case Ctlp_XOR_c:
4380      /*
4381      **   *             *(+)                  *(+)
4382      **  / \           /    \                /     \
4383      ** |   |   =>    *      *     =>      *         *
4384      ** |   |        / \    / \          /   \      / \
4385      ** r  XOR      r   *  r   *        *    NOT   *   g=q(p)
4386      **    / \         / \    / \      / \   /    / \
4387      **   p   q       q  NOT NOT p    r   f g    r  NOT
4388      **                  /   /                      /
4389      **                 p   q                      f=p(q)
4390      */
4391
4392      p = formula->left;
4393      q = formula->right;
4394      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
4395      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
4396
4397      if (p_qf && q_qf)
4398        break;
4399      else if (p_qf) {
4400        f = p;
4401        g = q;
4402      } else if (q_qf) {
4403        f = q;
4404        g = p;
4405      } else {
4406        if (FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
4407          /*
4408          **   *             *(+)                  *(+)
4409          **  / \           /    \                /     \
4410          ** |   |   =>    *      *     =>      *         *
4411          ** |   |        / \    / \          /   \      / \
4412          ** r  XOR      r   *  r   *        *     q    *   p
4413          **    / \         / \    / \      / \        / \
4414          **   p   q       q  NOT NOT p    r  NOT     r  NOT
4415          **                  /   /           /          /
4416          **                 p   q           p          q
4417          */
4418
4419          if (compareValue)
4420            parent->type = Ctlp_OR_c;
4421          parent->left = parent->right;
4422          parent->left->type = Ctlp_AND_c;
4423          parent->left->left->type = Ctlp_AND_c;
4424          parent->left->left->left = r;
4425          parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4426          parent->left->left->right->left = p;
4427          parent->left->right = q;
4428
4429          parent->right = FormulaCreateWithType(Ctlp_AND_c);
4430          parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4431          parent->right->left->left = Ctlp_FormulaDup(r);
4432          parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4433          parent->right->left->right->left = Ctlp_FormulaDup(q);
4434          parent->right->right = Ctlp_FormulaDup(p);
4435
4436          parent->top = 0;
4437          parent->left->top = 1;
4438          parent->right->top = 1;
4439          parent->left->compareValue = compareValue;
4440          parent->right->compareValue = compareValue;
4441          parent->left->right->states = (mdd_t *)parent->left;
4442          parent->right->right->states = (mdd_t *)parent->right;
4443
4444          FormulaConvertToForward(parent->left->right, compareValue);
4445          FormulaConvertToForward(parent->right->right, compareValue);
4446          break;
4447        } else if (!FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
4448          /*
4449          **   *             *(+)                   *(+)
4450          **  / \           /    \                /      \
4451          ** |   |   =>    *      *     =>      *          *
4452          ** |   |        / \    / \          /   \      /   \
4453          ** r  XOR      r   *  r   *        *    NOT   *    NOT
4454          **    / \         / \    / \      / \   /    / \   /
4455          **   p   q       q  NOT NOT p    r   p q    r   q p
4456          **                  /   /
4457          **                 p   q
4458          */
4459
4460          if (compareValue)
4461            parent->type = Ctlp_OR_c;
4462          parent->left = parent->right;
4463          parent->left->type = Ctlp_AND_c;
4464          parent->left->left->type = Ctlp_AND_c;
4465          parent->left->left->left = r;
4466          parent->left->left->right = p;
4467          parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4468          parent->left->right->left = q;
4469
4470          parent->right = FormulaCreateWithType(Ctlp_AND_c);
4471          parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4472          parent->right->left->left = Ctlp_FormulaDup(r);
4473          parent->right->left->right = Ctlp_FormulaDup(q);
4474          parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
4475          parent->right->right->left = Ctlp_FormulaDup(p);
4476
4477          parent->top = 0;
4478          parent->left->top = 1;
4479          parent->right->top = 1;
4480          parent->left->compareValue = compareValue;
4481          parent->right->compareValue = compareValue;
4482          parent->left->right->states = (mdd_t *)parent->left;
4483          parent->right->right->states = (mdd_t *)parent->right;
4484
4485          FormulaConvertToForward(parent->left->right, compareValue);
4486          FormulaConvertToForward(parent->right->right, compareValue);
4487          break;
4488        } else {
4489          f = p;
4490          g = q;
4491        }
4492      }
4493
4494      if (compareValue)
4495        parent->type = Ctlp_OR_c;
4496      parent->left = parent->right;
4497      parent->left->type = Ctlp_AND_c;
4498      parent->left->left = FormulaCreateWithType(Ctlp_AND_c);
4499      parent->left->left->left = r;
4500      parent->left->left->right = f;
4501      parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4502      parent->left->right->left = g;
4503
4504      parent->right = FormulaCreateWithType(Ctlp_AND_c);
4505      parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4506      parent->right->left->left = Ctlp_FormulaDup(r);
4507      parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4508      parent->right->left->right->left = Ctlp_FormulaDup(f);
4509      parent->right->right = Ctlp_FormulaDup(g);
4510
4511      parent->top = 0;
4512      parent->left->top = 1;
4513      parent->right->top = 1;
4514      parent->left->compareValue = compareValue;
4515      parent->right->compareValue = compareValue;
4516      parent->left->right->states = (mdd_t *)parent->left;
4517      parent->right->right->states = (mdd_t *)parent->right;
4518
4519      FormulaConvertToForward(parent->left->right, compareValue);
4520      FormulaConvertToForward(parent->right->right, compareValue);
4521      break;
4522
4523    case Ctlp_EQ_c:
4524      /*
4525      **   *              *(+)                   *(+)
4526      **  / \            /     \               /      \
4527      ** |   |   =>     *       *      =>    *          *
4528      ** |   |         / \     / \          / \      /     \
4529      ** r  EQ        r   *   r   *        *   g    *      NOT
4530      **    /\           / \     / \      / \      / \     /
4531      **   p  q         p   q  NOT NOT   r   f    r  NOT  g=q(p)
4532      **                       /   /                 /
4533      **                      p   q                 f=p(q)
4534      */
4535
4536      p = formula->left;
4537      q = formula->right;
4538      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
4539      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
4540
4541      same_order = 1;
4542      if (p_qf && q_qf)
4543        break;
4544      else if (p_qf) {
4545        f = p;
4546        g = q;
4547      } else if (q_qf) {
4548        f = q;
4549        g = p;
4550      } else {
4551        if (FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
4552          /*
4553          **   *              *(+)                   *(+)
4554          **  / \            /     \               /      \
4555          ** |   |   =>     *       *      =>    *          *
4556          ** |   |         / \     / \          / \      /     \
4557          ** r  EQ        r   *   r   *        *   p    *      NOT
4558          **    /\           / \     / \      / \      / \     /
4559          **   p  q         p   q  NOT NOT   r   q    r  NOT  q
4560          **                       /   /                 /
4561          **                      p   q                 p
4562          */
4563
4564          f = q;
4565          g = p;
4566          same_order = 0;
4567        } else if (!FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
4568          /*
4569          **   *              *(+)                   *(+)
4570          **  / \            /     \               /      \
4571          ** |   |   =>     *       *      =>    *          *
4572          ** |   |         / \     / \          / \      /     \
4573          ** r  EQ        r   *   r   *        *   q    *      NOT
4574          **    /\           / \     / \      / \      / \     /
4575          **   p  q         p   q  NOT NOT   r   p    r  NOT  p
4576          **                       /   /                 /
4577          **                      p   q                 q
4578          */
4579
4580          f = p;
4581          g = q;
4582          same_order = 0;
4583        } else {
4584          f = p;
4585          g = q;
4586        }
4587      }
4588
4589      if (compareValue)
4590        parent->type = Ctlp_OR_c;
4591      parent->left = parent->right;
4592      parent->left->type = Ctlp_AND_c;
4593      parent->left->left = FormulaCreateWithType(Ctlp_AND_c);
4594      parent->left->left->left = r;
4595      parent->left->left->right = f;
4596      parent->left->right = g;
4597
4598      parent->right = FormulaCreateWithType(Ctlp_AND_c);
4599      parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
4600      parent->right->left->left = Ctlp_FormulaDup(r);
4601      parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
4602      if (same_order)
4603        parent->right->left->right->left = Ctlp_FormulaDup(f);
4604      else
4605        parent->right->left->right->left = Ctlp_FormulaDup(g);
4606      parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
4607      if (same_order)
4608        parent->right->right->left = Ctlp_FormulaDup(g);
4609      else
4610        parent->right->right->left = Ctlp_FormulaDup(f);
4611
4612      parent->top = 0;
4613      parent->left->top = 1;
4614      parent->right->top = 1;
4615      parent->left->compareValue = compareValue;
4616      parent->right->compareValue = compareValue;
4617      parent->left->right->states = (mdd_t *)parent->left;
4618      parent->right->right->states = (mdd_t *)parent->right;
4619
4620      FormulaConvertToForward(parent->left->right, compareValue);
4621      FormulaConvertToForward(parent->right->right, compareValue);
4622      break;
4623
4624    case Ctlp_AX_c:
4625    case Ctlp_AG_c:
4626    case Ctlp_AF_c:
4627    case Ctlp_AU_c:
4628      fprintf(vis_stderr,
4629        "** ctl error : invalid node type in converting to forward formula.\n"
4630              );
4631      assert(0);
4632      break;
4633
4634    case Ctlp_ID_c:
4635    case Ctlp_TRUE_c:
4636    case Ctlp_FALSE_c:
4637      break;
4638
4639    default:
4640      fail("Unexpected type");
4641  }
4642}
4643
4644
4645/**Function********************************************************************
4646
4647  Synopsis    [Inserts compare nodes into forward formula.]
4648
4649  Description [Inserts compare nodes into forward formula.]
4650
4651  SideEffects []
4652
4653  SeeAlso     []
4654
4655******************************************************************************/
4656static void
4657FormulaInsertForwardCompareNodes(Ctlp_Formula_t *formula,
4658                                 Ctlp_Formula_t *parent,
4659                                 int compareValue)
4660{
4661  Ctlp_Formula_t *new_;
4662
4663  if (formula->top) {
4664    if (!parent) {
4665      new_ = FormulaCreateWithType(Ctlp_Cmp_c);
4666      memcpy((void *)new_, (void *)formula, sizeof(Ctlp_Formula_t));
4667      formula->type = Ctlp_Cmp_c;
4668      formula->left = new_;
4669      formula->right = FormulaCreateWithType(Ctlp_FALSE_c);
4670      formula->compareValue = compareValue;
4671    } else {
4672      new_ = FormulaCreateWithType(Ctlp_Cmp_c);
4673      new_->left = formula;
4674      new_->right = FormulaCreateWithType(Ctlp_FALSE_c);
4675      new_->compareValue = compareValue;
4676      if (parent->left == formula)
4677        parent->left = new_;
4678      else
4679        parent->right = new_;
4680    }
4681    return;
4682  }
4683  FormulaInsertForwardCompareNodes(formula->left, formula, compareValue);
4684  FormulaInsertForwardCompareNodes(formula->right, formula, compareValue);
4685}
4686
4687
4688/**Function********************************************************************
4689
4690  Synopsis    [Determines which conversion formula is better.]
4691
4692  Description [Determines which conversion formula is better between
4693  init ^ f != FALSE and init ^ !f == FALSE.]
4694
4695  SideEffects []
4696
4697  SeeAlso     []
4698
4699******************************************************************************/
4700static int
4701FormulaGetCompareValue(Ctlp_Formula_t *formula)
4702{
4703  int   compareValue;
4704
4705  if (FormulaIsConvertible(formula))
4706    compareValue = 1; /* check whether the result is not FALSE */
4707  else
4708    compareValue = 0; /* check whether the result is FALSE. */
4709
4710  return(compareValue);
4711}
4712
4713
4714/**Function********************************************************************
4715
4716  Synopsis    [Checks whether a formula can be converted to forward further.]
4717
4718  Description [Checks whether a formula can be converted to forward further.
4719  It returns 1 if it is convertible, and returns 0 if it is not convertible,
4720  and returns 2 if it is partially convertible.]
4721
4722  SideEffects []
4723
4724  SeeAlso     []
4725
4726******************************************************************************/
4727static int
4728FormulaIsConvertible(Ctlp_Formula_t *formula)
4729{
4730  int   convertible;
4731  int   value1, value2;
4732
4733  if (Ctlp_FormulaTestIsQuantifierFree(formula))
4734    convertible = 1;
4735  else if (formula->type == Ctlp_ID_c)
4736    convertible = 1;
4737  else if (formula->type == Ctlp_EX_c ||
4738           formula->type == Ctlp_EU_c ||
4739           formula->type == Ctlp_EF_c ||
4740           formula->type == Ctlp_EG_c) {
4741    convertible = 1;
4742  } else if (formula->type == Ctlp_NOT_c) {
4743    if (formula->left->type == Ctlp_NOT_c) {
4744      if (formula->left->left->type == Ctlp_EX_c ||
4745          formula->left->left->type == Ctlp_EU_c ||
4746          formula->left->left->type == Ctlp_EF_c ||
4747          formula->left->left->type == Ctlp_EG_c) {
4748        convertible = 1;
4749      } else {
4750        convertible = FormulaIsConvertible(formula->left->left);
4751      }
4752    } else {
4753      if (formula->left->type == Ctlp_EX_c ||
4754          formula->left->type == Ctlp_EU_c ||
4755          formula->left->type == Ctlp_EF_c ||
4756          formula->left->type == Ctlp_EG_c) {
4757        convertible = 0;
4758      } else {
4759        value1 = FormulaIsConvertible(formula->left);
4760        value2 = FormulaIsConvertible(formula->right);
4761        switch (formula->type) {
4762        case Ctlp_AND_c:
4763        case Ctlp_OR_c:
4764          convertible = (value1 & 0x1) * (value2 & 0x1);
4765          break;
4766        case Ctlp_THEN_c:
4767          convertible = value1 * (value2 & 0x1);
4768          break;
4769        default :
4770          convertible = 2;
4771          break;
4772        }
4773      }
4774    }
4775  } else {
4776    value1 = FormulaIsConvertible(formula->left);
4777    value2 = FormulaIsConvertible(formula->right);
4778    switch (formula->type) {
4779    case Ctlp_AND_c:
4780    case Ctlp_OR_c:
4781      convertible = value1 * value2;
4782      break;
4783    case Ctlp_THEN_c:
4784      convertible = (value1 & 0x1) * value2;
4785      break;
4786    default :
4787      convertible = 2;
4788      break;
4789    }
4790  }
4791
4792  return(convertible);
4793}
4794
4795
4796/**Function********************************************************************
4797
4798  Synopsis    [Replaces a simple formula with bottom.]
4799
4800  Description [This function is used in generating the witness formula from a
4801  w-ACTL formula in Beer's approach to vacuity detection.  Replaces a simple
4802  (propositional) subformula with bottom, which is FALSE for even negation
4803  parity and TRUE for odd negation parity.  An exception is made when the top
4804  node of the subformula is an implication.  In that case, the top node and the
4805  antecedent (left child) are retained in the replacement, while the
4806  consequent (right child) is replaced by bottom.]
4807
4808  SideEffects [none]
4809
4810  SeeAlso     [Ctlp_FormulaCreateWitnessFormula]
4811
4812******************************************************************************/
4813static Ctlp_Formula_t *
4814ReplaceSimpleFormula(
4815  Ctlp_Formula_t * formula)
4816{
4817  Ctlp_Formula_t *newFormula;
4818
4819  assert(formula->negation_parity == Ctlp_Even_c ||
4820         formula->negation_parity == Ctlp_Odd_c);
4821
4822  if (Ctlp_FormulaReadType(formula) == Ctlp_THEN_c) {
4823    Ctlp_Formula_t *leftFormula, *rightFormula;
4824    Ctlp_Formula_t *newLeftFormula, *newRightFormula;
4825
4826    leftFormula = Ctlp_FormulaReadLeftChild(formula);
4827    rightFormula = Ctlp_FormulaReadRightChild(formula);
4828    newLeftFormula = Ctlp_FormulaDup(leftFormula);
4829    newRightFormula = ReplaceSimpleFormula(rightFormula);
4830    return Ctlp_FormulaCreate(Ctlp_THEN_c,newLeftFormula,newRightFormula);
4831  }
4832
4833  fprintf(vis_stderr, "Replacing formula ");
4834  Ctlp_FormulaPrint(vis_stderr, formula);
4835  if (formula->negation_parity == Ctlp_Even_c){
4836    fprintf(vis_stderr, " by FALSE\n");
4837    newFormula = FormulaCreateWithType(Ctlp_FALSE_c);
4838  } else{
4839    fprintf(vis_stderr, " by TRUE\n");
4840    newFormula = FormulaCreateWithType(Ctlp_TRUE_c);
4841  }
4842  newFormula->negation_parity = formula->negation_parity;
4843  return(newFormula);
4844}
Note: See TracBrowser for help on using the repository browser.