source: vis_dev/glu-2.1/src/cuBdd/cuddUtil.c @ 8

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

src glu

File size: 103.8 KB
RevLine 
[8]1/**CFile***********************************************************************
2
3  FileName    [cuddUtil.c]
4
5  PackageName [cudd]
6
7  Synopsis    [Utility functions.]
8
9  Description [External procedures included in this module:
10                <ul>
11                <li> Cudd_PrintMinterm()
12                <li> Cudd_bddPrintCover()
13                <li> Cudd_PrintDebug()
14                <li> Cudd_DagSize()
15                <li> Cudd_EstimateCofactor()
16                <li> Cudd_EstimateCofactorSimple()
17                <li> Cudd_SharingSize()
18                <li> Cudd_CountMinterm()
19                <li> Cudd_EpdCountMinterm()
20                <li> Cudd_CountPath()
21                <li> Cudd_CountPathsToNonZero()
22                <li> Cudd_Support()
23                <li> Cudd_SupportIndex()
24                <li> Cudd_SupportSize()
25                <li> Cudd_VectorSupport()
26                <li> Cudd_VectorSupportIndex()
27                <li> Cudd_VectorSupportSize()
28                <li> Cudd_ClassifySupport()
29                <li> Cudd_CountLeaves()
30                <li> Cudd_bddPickOneCube()
31                <li> Cudd_bddPickOneMinterm()
32                <li> Cudd_bddPickArbitraryMinterms()
33                <li> Cudd_SubsetWithMaskVars()
34                <li> Cudd_FirstCube()
35                <li> Cudd_NextCube()
36                <li> Cudd_bddComputeCube()
37                <li> Cudd_addComputeCube()
38                <li> Cudd_FirstNode()
39                <li> Cudd_NextNode()
40                <li> Cudd_GenFree()
41                <li> Cudd_IsGenEmpty()
42                <li> Cudd_IndicesToCube()
43                <li> Cudd_PrintVersion()
44                <li> Cudd_AverageDistance()
45                <li> Cudd_Random()
46                <li> Cudd_Srandom()
47                <li> Cudd_Density()
48                </ul>
49        Internal procedures included in this module:
50                <ul>
51                <li> cuddP()
52                <li> cuddStCountfree()
53                <li> cuddCollectNodes()
54                <li> cuddNodeArray()
55                </ul>
56        Static procedures included in this module:
57                <ul>
58                <li> dp2()
59                <li> ddPrintMintermAux()
60                <li> ddDagInt()
61                <li> ddCountMintermAux()
62                <li> ddEpdCountMintermAux()
63                <li> ddCountPathAux()
64                <li> ddSupportStep()
65                <li> ddClearFlag()
66                <li> ddLeavesInt()
67                <li> ddPickArbitraryMinterms()
68                <li> ddPickRepresentativeCube()
69                <li> ddEpdFree()
70                </ul>]
71
72  Author      [Fabio Somenzi]
73
74  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
75
76  All rights reserved.
77
78  Redistribution and use in source and binary forms, with or without
79  modification, are permitted provided that the following conditions
80  are met:
81
82  Redistributions of source code must retain the above copyright
83  notice, this list of conditions and the following disclaimer.
84
85  Redistributions in binary form must reproduce the above copyright
86  notice, this list of conditions and the following disclaimer in the
87  documentation and/or other materials provided with the distribution.
88
89  Neither the name of the University of Colorado nor the names of its
90  contributors may be used to endorse or promote products derived from
91  this software without specific prior written permission.
92
93  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
94  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
95  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
96  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
97  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
98  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
99  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
100  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
101  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
102  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
103  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
104  POSSIBILITY OF SUCH DAMAGE.]
105
106******************************************************************************/
107
108#include "util.h"
109#include "cuddInt.h"
110
111/*---------------------------------------------------------------------------*/
112/* Constant declarations                                                     */
113/*---------------------------------------------------------------------------*/
114
115/* Random generator constants. */
116#define MODULUS1 2147483563
117#define LEQA1 40014
118#define LEQQ1 53668
119#define LEQR1 12211
120#define MODULUS2 2147483399
121#define LEQA2 40692
122#define LEQQ2 52774
123#define LEQR2 3791
124#define STAB_SIZE 64
125#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
126
127/*---------------------------------------------------------------------------*/
128/* Stucture declarations                                                     */
129/*---------------------------------------------------------------------------*/
130
131/*---------------------------------------------------------------------------*/
132/* Type declarations                                                         */
133/*---------------------------------------------------------------------------*/
134
135
136/*---------------------------------------------------------------------------*/
137/* Variable declarations                                                     */
138/*---------------------------------------------------------------------------*/
139
140#ifndef lint
141static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.78 2005/05/14 17:27:12 fabio Exp $";
142#endif
143
144static  DdNode  *background, *zero;
145
146static  long cuddRand = 0;
147static  long cuddRand2;
148static  long shuffleSelect;
149static  long shuffleTable[STAB_SIZE];
150
151/*---------------------------------------------------------------------------*/
152/* Macro declarations                                                        */
153/*---------------------------------------------------------------------------*/
154
155#define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ')
156
157#ifdef __cplusplus
158extern "C" {
159#endif
160
161/**AutomaticStart*************************************************************/
162
163/*---------------------------------------------------------------------------*/
164/* Static function prototypes                                                */
165/*---------------------------------------------------------------------------*/
166
167static int dp2 (DdManager *dd, DdNode *f, st_table *t);
168static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
169static int ddDagInt (DdNode *n);
170static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
171static int cuddEstimateCofactor (DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr);
172static DdNode * cuddUniqueLookup (DdManager * unique, int  index, DdNode * T, DdNode * E);
173static int cuddEstimateCofactorSimple (DdNode * node, int i);
174static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
175static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st_table *table);
176static double ddCountPathAux (DdNode *node, st_table *table);
177static double ddCountPathsToNonZero (DdNode * N, st_table * table);
178static void ddSupportStep (DdNode *f, int *support);
179static void ddClearFlag (DdNode *f);
180static int ddLeavesInt (DdNode *n);
181static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
182static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, int nvars, double *weight, char *string);
183static enum st_retval ddEpdFree (char * key, char * value, char * arg);
184
185/**AutomaticEnd***************************************************************/
186
187#ifdef __cplusplus
188}
189#endif
190
191/*---------------------------------------------------------------------------*/
192/* Definition of exported functions                                          */
193/*---------------------------------------------------------------------------*/
194
195
196/**Function********************************************************************
197
198  Synopsis    [Prints a disjoint sum of products.]
199
200  Description [Prints a disjoint sum of product cover for the function
201  rooted at node. Each product corresponds to a path from node to a
202  leaf node different from the logical zero, and different from the
203  background value. Uses the package default output file.  Returns 1
204  if successful; 0 otherwise.]
205
206  SideEffects [None]
207
208  SeeAlso     [Cudd_PrintDebug Cudd_bddPrintCover]
209
210******************************************************************************/
211int
212Cudd_PrintMinterm(
213  DdManager * manager,
214  DdNode * node)
215{
216    int         i, *list;
217
218    background = manager->background;
219    zero = Cudd_Not(manager->one);
220    list = ALLOC(int,manager->size);
221    if (list == NULL) {
222        manager->errorCode = CUDD_MEMORY_OUT;
223        return(0);
224    }
225    for (i = 0; i < manager->size; i++) list[i] = 2;
226    ddPrintMintermAux(manager,node,list);
227    FREE(list);
228    return(1);
229
230} /* end of Cudd_PrintMinterm */
231
232
233/**Function********************************************************************
234
235  Synopsis    [Prints a sum of prime implicants of a BDD.]
236
237  Description [Prints a sum of product cover for an incompletely
238  specified function given by a lower bound and an upper bound.  Each
239  product is a prime implicant obtained by expanding the product
240  corresponding to a path from node to the constant one.  Uses the
241  package default output file.  Returns 1 if successful; 0 otherwise.]
242
243  SideEffects [None]
244
245  SeeAlso     [Cudd_PrintMinterm]
246
247******************************************************************************/
248int
249Cudd_bddPrintCover(
250  DdManager *dd,
251  DdNode *l,
252  DdNode *u)
253{
254    int *array;
255    int q, result;
256    DdNode *lb;
257#ifdef DD_DEBUG
258    DdNode *cover;
259#endif
260
261    array = ALLOC(int, Cudd_ReadSize(dd));
262    if (array == NULL) return(0);
263    lb = l;
264    cuddRef(lb);
265#ifdef DD_DEBUG
266    cover = Cudd_ReadLogicZero(dd);
267    cuddRef(cover);
268#endif
269    while (lb != Cudd_ReadLogicZero(dd)) {
270        DdNode *implicant, *prime, *tmp;
271        int length;
272        implicant = Cudd_LargestCube(dd,lb,&length);
273        if (implicant == NULL) {
274            Cudd_RecursiveDeref(dd,lb);
275            FREE(array);
276            return(0);
277        }
278        cuddRef(implicant);
279        prime = Cudd_bddMakePrime(dd,implicant,u);
280        if (prime == NULL) {
281            Cudd_RecursiveDeref(dd,lb);
282            Cudd_RecursiveDeref(dd,implicant);
283            FREE(array);
284            return(0);
285        }
286        cuddRef(prime);
287        Cudd_RecursiveDeref(dd,implicant);
288        tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime));
289        if (tmp == NULL) {
290            Cudd_RecursiveDeref(dd,lb);
291            Cudd_RecursiveDeref(dd,prime);
292            FREE(array);
293            return(0);
294        }
295        cuddRef(tmp);
296        Cudd_RecursiveDeref(dd,lb);
297        lb = tmp;
298        result = Cudd_BddToCubeArray(dd,prime,array);
299        if (result == 0) {
300            Cudd_RecursiveDeref(dd,lb);
301            Cudd_RecursiveDeref(dd,prime);
302            FREE(array);
303            return(0);
304        }
305        for (q = 0; q < dd->size; q++) {
306            switch (array[q]) {
307            case 0:
308                (void) fprintf(dd->out, "0");
309                break;
310            case 1:
311                (void) fprintf(dd->out, "1");
312                break;
313            case 2:
314                (void) fprintf(dd->out, "-");
315                break;
316            default:
317                (void) fprintf(dd->out, "?");
318            }
319        }
320        (void) fprintf(dd->out, " 1\n");
321#ifdef DD_DEBUG
322        tmp = Cudd_bddOr(dd,prime,cover);
323        if (tmp == NULL) {
324            Cudd_RecursiveDeref(dd,cover);
325            Cudd_RecursiveDeref(dd,lb);
326            Cudd_RecursiveDeref(dd,prime);
327            FREE(array);
328            return(0);
329        }
330        cuddRef(tmp);
331        Cudd_RecursiveDeref(dd,cover);
332        cover = tmp;
333#endif
334        Cudd_RecursiveDeref(dd,prime);
335    }
336    (void) fprintf(dd->out, "\n");
337    Cudd_RecursiveDeref(dd,lb);
338    FREE(array);
339#ifdef DD_DEBUG
340    if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) {
341        Cudd_RecursiveDeref(dd,cover);
342        return(0);
343    }
344    Cudd_RecursiveDeref(dd,cover);
345#endif
346    return(1);
347
348} /* end of Cudd_bddPrintCover */
349
350
351/**Function********************************************************************
352
353  Synopsis    [Prints to the standard output a DD and its statistics.]
354
355  Description [Prints to the standard output a DD and its statistics.
356  The statistics include the number of nodes, the number of leaves, and
357  the number of minterms. (The number of minterms is the number of
358  assignments to the variables that cause the function to be different
359  from the logical zero (for BDDs) and from the background value (for
360  ADDs.) The statistics are printed if pr &gt; 0. Specifically:
361  <ul>
362  <li> pr = 0 : prints nothing
363  <li> pr = 1 : prints counts of nodes and minterms
364  <li> pr = 2 : prints counts + disjoint sum of product
365  <li> pr = 3 : prints counts + list of nodes
366  <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes
367  </ul>
368  For the purpose of counting the number of minterms, the function is
369  supposed to depend on n variables. Returns 1 if successful; 0 otherwise.]
370
371  SideEffects [None]
372
373  SeeAlso     [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm
374  Cudd_PrintMinterm]
375
376******************************************************************************/
377int
378Cudd_PrintDebug(
379  DdManager * dd,
380  DdNode * f,
381  int  n,
382  int  pr)
383{
384    DdNode *azero, *bzero;
385    int    nodes;
386    int    leaves;
387    double minterms;
388    int    retval = 1;
389
390    if (f == NULL) {
391        (void) fprintf(dd->out,": is the NULL DD\n");
392        (void) fflush(dd->out);
393        return(0);
394    }
395    azero = DD_ZERO(dd);
396    bzero = Cudd_Not(DD_ONE(dd));
397    if ((f == azero || f == bzero) && pr > 0){
398       (void) fprintf(dd->out,": is the zero DD\n");
399       (void) fflush(dd->out);
400       return(1);
401    }
402    if (pr > 0) {
403        nodes = Cudd_DagSize(f);
404        if (nodes == CUDD_OUT_OF_MEM) retval = 0;
405        leaves = Cudd_CountLeaves(f);
406        if (leaves == CUDD_OUT_OF_MEM) retval = 0;
407        minterms = Cudd_CountMinterm(dd, f, n);
408        if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
409        (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n",
410                       nodes, leaves, minterms);
411        if (pr > 2) {
412            if (!cuddP(dd, f)) retval = 0;
413        }
414        if (pr == 2 || pr > 3) {
415            if (!Cudd_PrintMinterm(dd,f)) retval = 0;
416            (void) fprintf(dd->out,"\n");
417        }
418        (void) fflush(dd->out);
419    }
420    return(retval);
421
422} /* end of Cudd_PrintDebug */
423
424
425/**Function********************************************************************
426
427  Synopsis    [Counts the number of nodes in a DD.]
428
429  Description [Counts the number of nodes in a DD. Returns the number
430  of nodes in the graph rooted at node.]
431
432  SideEffects [None]
433
434  SeeAlso     [Cudd_SharingSize Cudd_PrintDebug]
435
436******************************************************************************/
437int
438Cudd_DagSize(
439  DdNode * node)
440{
441    int i;     
442
443    i = ddDagInt(Cudd_Regular(node));
444    ddClearFlag(Cudd_Regular(node));
445
446    return(i);
447
448} /* end of Cudd_DagSize */
449
450
451/**Function********************************************************************
452
453  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
454
455  Description [Estimates the number of nodes in a cofactor of a DD.
456  Returns an estimate of the number of nodes in a cofactor of
457  the graph rooted at node with respect to the variable whose index is i.
458  In case of failure, returns CUDD_OUT_OF_MEM.
459  This function uses a refinement of the algorithm of Cabodi et al.
460  (ICCAD96). The refinement allows the procedure to account for part
461  of the recombination that may occur in the part of the cofactor above
462  the cofactoring variable. This procedure does no create any new node.
463  It does keep a small table of results; therefore it may run out of memory.
464  If this is a concern, one should use Cudd_EstimateCofactorSimple, which
465  is faster, does not allocate any memory, but is less accurate.]
466
467  SideEffects [None]
468
469  SeeAlso     [Cudd_DagSize Cudd_EstimateCofactorSimple]
470
471******************************************************************************/
472int
473Cudd_EstimateCofactor(
474  DdManager *dd /* manager */,
475  DdNode * f    /* function */,
476  int i         /* index of variable */,
477  int phase     /* 1: positive; 0: negative */
478  )
479{
480    int val;
481    DdNode *ptr;
482    st_table *table;
483
484    table = st_init_table(st_ptrcmp,st_ptrhash);
485    if (table == NULL) return(CUDD_OUT_OF_MEM);
486    val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr);
487    ddClearFlag(Cudd_Regular(f));
488    st_free_table(table);
489
490    return(val);
491
492} /* end of Cudd_EstimateCofactor */
493
494
495/**Function********************************************************************
496
497  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
498
499  Description [Estimates the number of nodes in a cofactor of a DD.
500  Returns an estimate of the number of nodes in the positive cofactor of
501  the graph rooted at node with respect to the variable whose index is i.
502  This procedure implements with minor changes the algorithm of Cabodi et al.
503  (ICCAD96). It does not allocate any memory, it does not change the
504  state of the manager, and it is fast. However, it has been observed to
505  overestimate the size of the cofactor by as much as a factor of 2.]
506
507  SideEffects [None]
508
509  SeeAlso     [Cudd_DagSize]
510
511******************************************************************************/
512int
513Cudd_EstimateCofactorSimple(
514  DdNode * node,
515  int i)
516{
517    int val;   
518
519    val = cuddEstimateCofactorSimple(Cudd_Regular(node),i);
520    ddClearFlag(Cudd_Regular(node));
521
522    return(val);
523
524} /* end of Cudd_EstimateCofactorSimple */
525
526
527/**Function********************************************************************
528
529  Synopsis    [Counts the number of nodes in an array of DDs.]
530
531  Description [Counts the number of nodes in an array of DDs. Shared
532  nodes are counted only once.  Returns the total number of nodes.]
533
534  SideEffects [None]
535
536  SeeAlso     [Cudd_DagSize]
537
538******************************************************************************/
539int
540Cudd_SharingSize(
541  DdNode ** nodeArray,
542  int  n)
543{
544    int i,j;   
545
546    i = 0;
547    for (j = 0; j < n; j++) {
548        i += ddDagInt(Cudd_Regular(nodeArray[j]));
549    }
550    for (j = 0; j < n; j++) {
551        ddClearFlag(Cudd_Regular(nodeArray[j]));
552    }
553    return(i);
554
555} /* end of Cudd_SharingSize */
556
557
558/**Function********************************************************************
559
560  Synopsis    [Counts the number of minterms of a DD.]
561
562  Description [Counts the number of minterms of a DD. The function is
563  assumed to depend on nvars variables. The minterm count is
564  represented as a double, to allow for a larger number of variables.
565  Returns the number of minterms of the function rooted at node if
566  successful; (double) CUDD_OUT_OF_MEM otherwise.]
567
568  SideEffects [None]
569
570  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
571
572******************************************************************************/
573double
574Cudd_CountMinterm(
575  DdManager * manager,
576  DdNode * node,
577  int  nvars)
578{
579    double      max;
580    DdHashTable *table;
581    double      res;
582    CUDD_VALUE_TYPE epsilon;
583
584    background = manager->background;
585    zero = Cudd_Not(manager->one);
586   
587    max = pow(2.0,(double)nvars);
588    table = cuddHashTableInit(manager,1,2);
589    if (table == NULL) {
590        return((double)CUDD_OUT_OF_MEM);
591    }
592    epsilon = Cudd_ReadEpsilon(manager);
593    Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
594    res = ddCountMintermAux(node,max,table);
595    cuddHashTableQuit(table);
596    Cudd_SetEpsilon(manager,epsilon);
597
598    return(res);
599
600} /* end of Cudd_CountMinterm */
601
602
603/**Function********************************************************************
604
605  Synopsis    [Counts the number of paths of a DD.]
606
607  Description [Counts the number of paths of a DD.  Paths to all
608  terminal nodes are counted. The path count is represented as a
609  double, to allow for a larger number of variables.  Returns the
610  number of paths of the function rooted at node if successful;
611  (double) CUDD_OUT_OF_MEM otherwise.]
612
613  SideEffects [None]
614
615  SeeAlso     [Cudd_CountMinterm]
616
617******************************************************************************/
618double
619Cudd_CountPath(
620  DdNode * node)
621{
622
623    st_table    *table;
624    double      i;     
625
626    table = st_init_table(st_ptrcmp,st_ptrhash);
627    if (table == NULL) {
628        return((double)CUDD_OUT_OF_MEM);
629    }
630    i = ddCountPathAux(Cudd_Regular(node),table);
631    st_foreach(table, cuddStCountfree, NULL);
632    st_free_table(table);
633    return(i);
634
635} /* end of Cudd_CountPath */
636
637
638/**Function********************************************************************
639
640  Synopsis    [Counts the number of minterms of a DD with extended precision.]
641
642  Description [Counts the number of minterms of a DD with extended precision.
643  The function is assumed to depend on nvars variables. The minterm count is
644  represented as an EpDouble, to allow any number of variables.
645  Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.]
646
647  SideEffects [None]
648
649  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
650
651******************************************************************************/
652int
653Cudd_EpdCountMinterm(
654  DdManager * manager,
655  DdNode * node,
656  int  nvars,
657  EpDouble * epd)
658{
659    EpDouble    max, tmp;
660    st_table    *table;
661    int         status;
662
663    background = manager->background;
664    zero = Cudd_Not(manager->one);
665   
666    EpdPow2(nvars, &max);
667    table = st_init_table(EpdCmp, st_ptrhash);
668    if (table == NULL) {
669        EpdMakeZero(epd, 0);
670        return(CUDD_OUT_OF_MEM);
671    }
672    status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table);
673    st_foreach(table, ddEpdFree, NULL);
674    st_free_table(table);
675    if (status == CUDD_OUT_OF_MEM) {
676        EpdMakeZero(epd, 0);
677        return(CUDD_OUT_OF_MEM);
678    }
679    if (Cudd_IsComplement(node)) {
680        EpdSubtract3(&max, epd, &tmp);
681        EpdCopy(&tmp, epd);
682    }
683    return(0);
684
685} /* end of Cudd_EpdCountMinterm */
686
687
688/**Function********************************************************************
689
690  Synopsis    [Counts the number of paths to a non-zero terminal of a DD.]
691
692  Description [Counts the number of paths to a non-zero terminal of a
693  DD.  The path count is
694  represented as a double, to allow for a larger number of variables.
695  Returns the number of paths of the function rooted at node.]
696
697  SideEffects [None]
698
699  SeeAlso     [Cudd_CountMinterm Cudd_CountPath]
700
701******************************************************************************/
702double
703Cudd_CountPathsToNonZero(
704  DdNode * node)
705{
706
707    st_table    *table;
708    double      i;     
709
710    table = st_init_table(st_ptrcmp,st_ptrhash);
711    if (table == NULL) {
712        return((double)CUDD_OUT_OF_MEM);
713    }
714    i = ddCountPathsToNonZero(node,table);
715    st_foreach(table, cuddStCountfree, NULL);
716    st_free_table(table);
717    return(i);
718
719} /* end of Cudd_CountPathsToNonZero */
720
721
722/**Function********************************************************************
723
724  Synopsis    [Finds the variables on which a DD depends.]
725
726  Description [Finds the variables on which a DD depends.
727  Returns a BDD consisting of the product of the variables if
728  successful; NULL otherwise.]
729
730  SideEffects [None]
731
732  SeeAlso     [Cudd_VectorSupport Cudd_ClassifySupport]
733
734******************************************************************************/
735DdNode *
736Cudd_Support(
737  DdManager * dd /* manager */,
738  DdNode * f /* DD whose support is sought */)
739{
740    int *support;
741    DdNode *res, *tmp, *var;
742    int i,j;
743    int size;
744
745    /* Allocate and initialize support array for ddSupportStep. */
746    size = ddMax(dd->size, dd->sizeZ);
747    support = ALLOC(int,size);
748    if (support == NULL) {
749        dd->errorCode = CUDD_MEMORY_OUT;
750        return(NULL);
751    }
752    for (i = 0; i < size; i++) {
753        support[i] = 0;
754    }
755
756    /* Compute support and clean up markers. */
757    ddSupportStep(Cudd_Regular(f),support);
758    ddClearFlag(Cudd_Regular(f));
759
760    /* Transform support from array to cube. */
761    do {
762        dd->reordered = 0;
763        res = DD_ONE(dd);
764        cuddRef(res);
765        for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
766            i = (j >= dd->size) ? j : dd->invperm[j];
767            if (support[i] == 1) {
768                /* The following call to cuddUniqueInter is guaranteed
769                ** not to trigger reordering because the node we look up
770                ** already exists. */ 
771                var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
772                cuddRef(var);
773                tmp = cuddBddAndRecur(dd,res,var);
774                if (tmp == NULL) {
775                    Cudd_RecursiveDeref(dd,res);
776                    Cudd_RecursiveDeref(dd,var);
777                    res = NULL;
778                    break;
779                }
780                cuddRef(tmp);
781                Cudd_RecursiveDeref(dd,res);
782                Cudd_RecursiveDeref(dd,var);
783                res = tmp;
784            }
785        }
786    } while (dd->reordered == 1);
787
788    FREE(support);
789    if (res != NULL) cuddDeref(res);
790    return(res);
791
792} /* end of Cudd_Support */
793
794
795/**Function********************************************************************
796
797  Synopsis    [Finds the variables on which a DD depends.]
798
799  Description [Finds the variables on which a DD depends.  Returns an
800  index array of the variables if successful; NULL otherwise.  The
801  size of the array equals the number of variables in the manager.
802  Each entry of the array is 1 if the corresponding variable is in the
803  support of the DD and 0 otherwise.]
804
805  SideEffects [None]
806
807  SeeAlso     [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
808
809******************************************************************************/
810int *
811Cudd_SupportIndex(
812  DdManager * dd /* manager */,
813  DdNode * f /* DD whose support is sought */)
814{
815    int *support;
816    int i;
817    int size;
818
819    /* Allocate and initialize support array for ddSupportStep. */
820    size = ddMax(dd->size, dd->sizeZ);
821    support = ALLOC(int,size);
822    if (support == NULL) {
823        dd->errorCode = CUDD_MEMORY_OUT;
824        return(NULL);
825    }
826    for (i = 0; i < size; i++) {
827        support[i] = 0;
828    }
829
830    /* Compute support and clean up markers. */
831    ddSupportStep(Cudd_Regular(f),support);
832    ddClearFlag(Cudd_Regular(f));
833
834    return(support);
835
836} /* end of Cudd_SupportIndex */
837
838
839/**Function********************************************************************
840
841  Synopsis    [Counts the variables on which a DD depends.]
842
843  Description [Counts the variables on which a DD depends.
844  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
845  otherwise.]
846
847  SideEffects [None]
848
849  SeeAlso     [Cudd_Support]
850
851******************************************************************************/
852int
853Cudd_SupportSize(
854  DdManager * dd /* manager */,
855  DdNode * f /* DD whose support size is sought */)
856{
857    int *support;
858    int i;
859    int size;
860    int count;
861
862    /* Allocate and initialize support array for ddSupportStep. */
863    size = ddMax(dd->size, dd->sizeZ);
864    support = ALLOC(int,size);
865    if (support == NULL) {
866        dd->errorCode = CUDD_MEMORY_OUT;
867        return(CUDD_OUT_OF_MEM);
868    }
869    for (i = 0; i < size; i++) {
870        support[i] = 0;
871    }
872
873    /* Compute support and clean up markers. */
874    ddSupportStep(Cudd_Regular(f),support);
875    ddClearFlag(Cudd_Regular(f));
876
877    /* Count support variables. */
878    count = 0;
879    for (i = 0; i < size; i++) {
880        if (support[i] == 1) count++;
881    }
882
883    FREE(support);
884    return(count);
885
886} /* end of Cudd_SupportSize */
887
888
889/**Function********************************************************************
890
891  Synopsis    [Finds the variables on which a set of DDs depends.]
892
893  Description [Finds the variables on which a set of DDs depends.
894  The set must contain either BDDs and ADDs, or ZDDs.
895  Returns a BDD consisting of the product of the variables if
896  successful; NULL otherwise.]
897
898  SideEffects [None]
899
900  SeeAlso     [Cudd_Support Cudd_ClassifySupport]
901
902******************************************************************************/
903DdNode *
904Cudd_VectorSupport(
905  DdManager * dd /* manager */,
906  DdNode ** F /* array of DDs whose support is sought */,
907  int  n /* size of the array */)
908{
909    int *support;
910    DdNode *res, *tmp, *var;
911    int i,j;
912    int size;
913
914    /* Allocate and initialize support array for ddSupportStep. */
915    size = ddMax(dd->size, dd->sizeZ);
916    support = ALLOC(int,size);
917    if (support == NULL) {
918        dd->errorCode = CUDD_MEMORY_OUT;
919        return(NULL);
920    }
921    for (i = 0; i < size; i++) {
922        support[i] = 0;
923    }
924
925    /* Compute support and clean up markers. */
926    for (i = 0; i < n; i++) {
927        ddSupportStep(Cudd_Regular(F[i]),support);
928    }
929    for (i = 0; i < n; i++) {
930        ddClearFlag(Cudd_Regular(F[i]));
931    }
932
933    /* Transform support from array to cube. */
934    res = DD_ONE(dd);
935    cuddRef(res);
936    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
937        i = (j >= dd->size) ? j : dd->invperm[j];
938        if (support[i] == 1) {
939            var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
940            cuddRef(var);
941            tmp = Cudd_bddAnd(dd,res,var);
942            if (tmp == NULL) {
943                Cudd_RecursiveDeref(dd,res);
944                Cudd_RecursiveDeref(dd,var);
945                FREE(support);
946                return(NULL);
947            }
948            cuddRef(tmp);
949            Cudd_RecursiveDeref(dd,res);
950            Cudd_RecursiveDeref(dd,var);
951            res = tmp;
952        }
953    }
954
955    FREE(support);
956    cuddDeref(res);
957    return(res);
958
959} /* end of Cudd_VectorSupport */
960
961
962/**Function********************************************************************
963
964  Synopsis    [Finds the variables on which a set of DDs depends.]
965
966  Description [Finds the variables on which a set of DDs depends.
967  The set must contain either BDDs and ADDs, or ZDDs.
968  Returns an index array of the variables if successful; NULL otherwise.]
969
970  SideEffects [None]
971
972  SeeAlso     [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport]
973
974******************************************************************************/
975int *
976Cudd_VectorSupportIndex(
977  DdManager * dd /* manager */,
978  DdNode ** F /* array of DDs whose support is sought */,
979  int  n /* size of the array */)
980{
981    int *support;
982    int i;
983    int size;
984
985    /* Allocate and initialize support array for ddSupportStep. */
986    size = ddMax(dd->size, dd->sizeZ);
987    support = ALLOC(int,size);
988    if (support == NULL) {
989        dd->errorCode = CUDD_MEMORY_OUT;
990        return(NULL);
991    }
992    for (i = 0; i < size; i++) {
993        support[i] = 0;
994    }
995
996    /* Compute support and clean up markers. */
997    for (i = 0; i < n; i++) {
998        ddSupportStep(Cudd_Regular(F[i]),support);
999    }
1000    for (i = 0; i < n; i++) {
1001        ddClearFlag(Cudd_Regular(F[i]));
1002    }
1003
1004    return(support);
1005
1006} /* end of Cudd_VectorSupportIndex */
1007
1008
1009/**Function********************************************************************
1010
1011  Synopsis    [Counts the variables on which a set of DDs depends.]
1012
1013  Description [Counts the variables on which a set of DDs depends.
1014  The set must contain either BDDs and ADDs, or ZDDs.
1015  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
1016  otherwise.]
1017
1018  SideEffects [None]
1019
1020  SeeAlso     [Cudd_VectorSupport Cudd_SupportSize]
1021
1022******************************************************************************/
1023int
1024Cudd_VectorSupportSize(
1025  DdManager * dd /* manager */,
1026  DdNode ** F /* array of DDs whose support is sought */,
1027  int  n /* size of the array */)
1028{
1029    int *support;
1030    int i;
1031    int size;
1032    int count;
1033
1034    /* Allocate and initialize support array for ddSupportStep. */
1035    size = ddMax(dd->size, dd->sizeZ);
1036    support = ALLOC(int,size);
1037    if (support == NULL) {
1038        dd->errorCode = CUDD_MEMORY_OUT;
1039        return(CUDD_OUT_OF_MEM);
1040    }
1041    for (i = 0; i < size; i++) {
1042        support[i] = 0;
1043    }
1044
1045    /* Compute support and clean up markers. */
1046    for (i = 0; i < n; i++) {
1047        ddSupportStep(Cudd_Regular(F[i]),support);
1048    }
1049    for (i = 0; i < n; i++) {
1050        ddClearFlag(Cudd_Regular(F[i]));
1051    }
1052
1053    /* Count vriables in support. */
1054    count = 0;
1055    for (i = 0; i < size; i++) {
1056        if (support[i] == 1) count++;
1057    }
1058
1059    FREE(support);
1060    return(count);
1061
1062} /* end of Cudd_VectorSupportSize */
1063
1064
1065/**Function********************************************************************
1066
1067  Synopsis    [Classifies the variables in the support of two DDs.]
1068
1069  Description [Classifies the variables in the support of two DDs
1070  <code>f</code> and <code>g</code>, depending on whther they appear
1071  in both DDs, only in <code>f</code>, or only in <code>g</code>.
1072  Returns 1 if successful; 0 otherwise.]
1073
1074  SideEffects [The cubes of the three classes of variables are
1075  returned as side effects.]
1076
1077  SeeAlso     [Cudd_Support Cudd_VectorSupport]
1078
1079******************************************************************************/
1080int
1081Cudd_ClassifySupport(
1082  DdManager * dd /* manager */,
1083  DdNode * f /* first DD */,
1084  DdNode * g /* second DD */,
1085  DdNode ** common /* cube of shared variables */,
1086  DdNode ** onlyF /* cube of variables only in f */,
1087  DdNode ** onlyG /* cube of variables only in g */)
1088{
1089    int *supportF, *supportG;
1090    DdNode *tmp, *var;
1091    int i,j;
1092    int size;
1093
1094    /* Allocate and initialize support arrays for ddSupportStep. */
1095    size = ddMax(dd->size, dd->sizeZ);
1096    supportF = ALLOC(int,size);
1097    if (supportF == NULL) {
1098        dd->errorCode = CUDD_MEMORY_OUT;
1099        return(0);
1100    }
1101    supportG = ALLOC(int,size);
1102    if (supportG == NULL) {
1103        dd->errorCode = CUDD_MEMORY_OUT;
1104        FREE(supportF);
1105        return(0);
1106    }
1107    for (i = 0; i < size; i++) {
1108        supportF[i] = 0;
1109        supportG[i] = 0;
1110    }
1111
1112    /* Compute supports and clean up markers. */
1113    ddSupportStep(Cudd_Regular(f),supportF);
1114    ddClearFlag(Cudd_Regular(f));
1115    ddSupportStep(Cudd_Regular(g),supportG);
1116    ddClearFlag(Cudd_Regular(g));
1117
1118    /* Classify variables and create cubes. */
1119    *common = *onlyF = *onlyG = DD_ONE(dd);
1120    cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG);
1121    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
1122        i = (j >= dd->size) ? j : dd->invperm[j];
1123        if (supportF[i] == 0 && supportG[i] == 0) continue;
1124        var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
1125        cuddRef(var);
1126        if (supportG[i] == 0) {
1127            tmp = Cudd_bddAnd(dd,*onlyF,var);
1128            if (tmp == NULL) {
1129                Cudd_RecursiveDeref(dd,*common);
1130                Cudd_RecursiveDeref(dd,*onlyF);
1131                Cudd_RecursiveDeref(dd,*onlyG);
1132                Cudd_RecursiveDeref(dd,var);
1133                FREE(supportF); FREE(supportG);
1134                return(0);
1135            }
1136            cuddRef(tmp);
1137            Cudd_RecursiveDeref(dd,*onlyF);
1138            *onlyF = tmp;
1139        } else if (supportF[i] == 0) {
1140            tmp = Cudd_bddAnd(dd,*onlyG,var);
1141            if (tmp == NULL) {
1142                Cudd_RecursiveDeref(dd,*common);
1143                Cudd_RecursiveDeref(dd,*onlyF);
1144                Cudd_RecursiveDeref(dd,*onlyG);
1145                Cudd_RecursiveDeref(dd,var);
1146                FREE(supportF); FREE(supportG);
1147                return(0);
1148            }
1149            cuddRef(tmp);
1150            Cudd_RecursiveDeref(dd,*onlyG);
1151            *onlyG = tmp;
1152        } else {
1153            tmp = Cudd_bddAnd(dd,*common,var);
1154            if (tmp == NULL) {
1155                Cudd_RecursiveDeref(dd,*common);
1156                Cudd_RecursiveDeref(dd,*onlyF);
1157                Cudd_RecursiveDeref(dd,*onlyG);
1158                Cudd_RecursiveDeref(dd,var);
1159                FREE(supportF); FREE(supportG);
1160                return(0);
1161            }
1162            cuddRef(tmp);
1163            Cudd_RecursiveDeref(dd,*common);
1164            *common = tmp;
1165        }
1166        Cudd_RecursiveDeref(dd,var);
1167    }
1168
1169    FREE(supportF); FREE(supportG);
1170    cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG);
1171    return(1);
1172
1173} /* end of Cudd_ClassifySupport */
1174
1175
1176/**Function********************************************************************
1177
1178  Synopsis    [Counts the number of leaves in a DD.]
1179
1180  Description [Counts the number of leaves in a DD. Returns the number
1181  of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM
1182  otherwise.]
1183
1184  SideEffects [None]
1185
1186  SeeAlso     [Cudd_PrintDebug]
1187
1188******************************************************************************/
1189int
1190Cudd_CountLeaves(
1191  DdNode * node)
1192{
1193    int i;     
1194
1195    i = ddLeavesInt(Cudd_Regular(node));
1196    ddClearFlag(Cudd_Regular(node));
1197    return(i);
1198
1199} /* end of Cudd_CountLeaves */
1200
1201
1202/**Function********************************************************************
1203
1204  Synopsis    [Picks one on-set cube randomly from the given DD.]
1205
1206  Description [Picks one on-set cube randomly from the given DD. The
1207  cube is written into an array of characters.  The array must have at
1208  least as many entries as there are variables. Returns 1 if
1209  successful; 0 otherwise.]
1210
1211  SideEffects [None]
1212
1213  SeeAlso     [Cudd_bddPickOneMinterm]
1214
1215******************************************************************************/
1216int
1217Cudd_bddPickOneCube(
1218  DdManager * ddm,
1219  DdNode * node,
1220  char * string)
1221{
1222    DdNode *N, *T, *E;
1223    DdNode *one, *bzero;
1224    char   dir;
1225    int    i;
1226
1227    if (string == NULL || node == NULL) return(0);
1228
1229    /* The constant 0 function has no on-set cubes. */
1230    one = DD_ONE(ddm);
1231    bzero = Cudd_Not(one);
1232    if (node == bzero) return(0);
1233
1234    for (i = 0; i < ddm->size; i++) string[i] = 2;
1235
1236    for (;;) {
1237
1238        if (node == one) break;
1239
1240        N = Cudd_Regular(node);
1241
1242        T = cuddT(N); E = cuddE(N);
1243        if (Cudd_IsComplement(node)) {
1244            T = Cudd_Not(T); E = Cudd_Not(E);
1245        }
1246        if (T == bzero) {
1247            string[N->index] = 0;
1248            node = E;
1249        } else if (E == bzero) {
1250            string[N->index] = 1;
1251            node = T;
1252        } else {
1253            dir = (char) ((Cudd_Random() & 0x2000) >> 13);
1254            string[N->index] = dir;
1255            node = dir ? T : E;
1256        }
1257    }
1258    return(1);
1259
1260} /* end of Cudd_bddPickOneCube */
1261
1262
1263/**Function********************************************************************
1264
1265  Synopsis    [Picks one on-set minterm randomly from the given DD.]
1266
1267  Description [Picks one on-set minterm randomly from the given
1268  DD. The minterm is in terms of <code>vars</code>. The array
1269  <code>vars</code> should contain at least all variables in the
1270  support of <code>f</code>; if this condition is not met the minterm
1271  built by this procedure may not be contained in
1272  <code>f</code>. Builds a BDD for the minterm and returns a pointer
1273  to it if successful; NULL otherwise. There are three reasons why the
1274  procedure may fail:
1275  <ul>
1276  <li> It may run out of memory;
1277  <li> the function <code>f</code> may be the constant 0;
1278  <li> the minterm may not be contained in <code>f</code>.
1279  </ul>]
1280
1281  SideEffects [None]
1282
1283  SeeAlso     [Cudd_bddPickOneCube]
1284
1285******************************************************************************/
1286DdNode *
1287Cudd_bddPickOneMinterm(
1288  DdManager * dd /* manager */,
1289  DdNode * f /* function from which to pick one minterm */,
1290  DdNode ** vars /* array of variables */,
1291  int  n /* size of <code>vars</code> */)
1292{
1293    char *string;
1294    int i, size;
1295    int *indices;
1296    int result;
1297    DdNode *old, *neW;
1298
1299    size = dd->size;
1300    string = ALLOC(char, size);
1301    if (string == NULL) {
1302        dd->errorCode = CUDD_MEMORY_OUT;
1303        return(NULL);
1304    }
1305    indices = ALLOC(int,n);
1306    if (indices == NULL) {
1307        dd->errorCode = CUDD_MEMORY_OUT;
1308        FREE(string);
1309        return(NULL);
1310    }
1311
1312    for (i = 0; i < n; i++) {
1313        indices[i] = vars[i]->index;
1314    }
1315
1316    result = Cudd_bddPickOneCube(dd,f,string);
1317    if (result == 0) {
1318        FREE(string);
1319        FREE(indices);
1320        return(NULL);
1321    }
1322
1323    /* Randomize choice for don't cares. */
1324    for (i = 0; i < n; i++) {
1325        if (string[indices[i]] == 2) 
1326            string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5);
1327    }
1328
1329    /* Build result BDD. */
1330    old = Cudd_ReadOne(dd);
1331    cuddRef(old);
1332
1333    for (i = n-1; i >= 0; i--) {
1334        neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0));
1335        if (neW == NULL) {
1336            FREE(string);
1337            FREE(indices);
1338            Cudd_RecursiveDeref(dd,old);
1339            return(NULL);
1340        }
1341        cuddRef(neW);
1342        Cudd_RecursiveDeref(dd,old);
1343        old = neW;
1344    }
1345
1346#ifdef DD_DEBUG
1347    /* Test. */
1348    if (Cudd_bddLeq(dd,old,f)) {
1349        cuddDeref(old);
1350    } else {
1351        Cudd_RecursiveDeref(dd,old);
1352        old = NULL;
1353    }
1354#else
1355    cuddDeref(old);
1356#endif
1357
1358    FREE(string);
1359    FREE(indices);
1360    return(old);
1361
1362}  /* end of Cudd_bddPickOneMinterm */
1363
1364
1365/**Function********************************************************************
1366
1367  Synopsis    [Picks k on-set minterms evenly distributed from given DD.]
1368
1369  Description [Picks k on-set minterms evenly distributed from given DD.
1370  The minterms are in terms of <code>vars</code>. The array
1371  <code>vars</code> should contain at least all variables in the
1372  support of <code>f</code>; if this condition is not met the minterms
1373  built by this procedure may not be contained in
1374  <code>f</code>. Builds an array of BDDs for the minterms and returns a
1375  pointer to it if successful; NULL otherwise. There are three reasons
1376  why the procedure may fail:
1377  <ul>
1378  <li> It may run out of memory;
1379  <li> the function <code>f</code> may be the constant 0;
1380  <li> the minterms may not be contained in <code>f</code>.
1381  </ul>]
1382
1383  SideEffects [None]
1384
1385  SeeAlso     [Cudd_bddPickOneMinterm Cudd_bddPickOneCube]
1386
1387******************************************************************************/
1388DdNode **
1389Cudd_bddPickArbitraryMinterms(
1390  DdManager * dd /* manager */,
1391  DdNode * f /* function from which to pick k minterms */,
1392  DdNode ** vars /* array of variables */,
1393  int  n /* size of <code>vars</code> */,
1394  int  k /* number of minterms to find */)
1395{
1396    char **string;
1397    int i, j, l, size;
1398    int *indices;
1399    int result;
1400    DdNode **old, *neW;
1401    double minterms;
1402    char *saveString;
1403    int saveFlag, savePoint, isSame;
1404
1405    minterms = Cudd_CountMinterm(dd,f,n);
1406    if ((double)k > minterms) {
1407        return(NULL);
1408    }
1409
1410    size = dd->size;
1411    string = ALLOC(char *, k);
1412    if (string == NULL) {
1413        dd->errorCode = CUDD_MEMORY_OUT;
1414        return(NULL);
1415    }
1416    for (i = 0; i < k; i++) {
1417        string[i] = ALLOC(char, size + 1);
1418        if (string[i] == NULL) {
1419            for (j = 0; j < i; j++)
1420                FREE(string[i]);
1421            FREE(string);
1422            dd->errorCode = CUDD_MEMORY_OUT;
1423            return(NULL);
1424        }
1425        for (j = 0; j < size; j++) string[i][j] = '2';
1426        string[i][size] = '\0';
1427    }
1428    indices = ALLOC(int,n);
1429    if (indices == NULL) {
1430        dd->errorCode = CUDD_MEMORY_OUT;
1431        for (i = 0; i < k; i++)
1432            FREE(string[i]);
1433        FREE(string);
1434        return(NULL);
1435    }
1436
1437    for (i = 0; i < n; i++) {
1438        indices[i] = vars[i]->index;
1439    }
1440
1441    result = ddPickArbitraryMinterms(dd,f,n,k,string);
1442    if (result == 0) {
1443        for (i = 0; i < k; i++)
1444            FREE(string[i]);
1445        FREE(string);
1446        FREE(indices);
1447        return(NULL);
1448    }
1449
1450    old = ALLOC(DdNode *, k);
1451    if (old == NULL) {
1452        dd->errorCode = CUDD_MEMORY_OUT;
1453        for (i = 0; i < k; i++)
1454            FREE(string[i]);
1455        FREE(string);
1456        FREE(indices);
1457        return(NULL);
1458    }
1459    saveString = ALLOC(char, size + 1);
1460    if (saveString == NULL) {
1461        dd->errorCode = CUDD_MEMORY_OUT;
1462        for (i = 0; i < k; i++)
1463            FREE(string[i]);
1464        FREE(string);
1465        FREE(indices);
1466        FREE(old);
1467        return(NULL);
1468    }
1469    saveFlag = 0;
1470
1471    /* Build result BDD array. */
1472    for (i = 0; i < k; i++) {
1473        isSame = 0;
1474        if (!saveFlag) {
1475            for (j = i + 1; j < k; j++) {
1476                if (strcmp(string[i], string[j]) == 0) {
1477                    savePoint = i;
1478                    strcpy(saveString, string[i]);
1479                    saveFlag = 1;
1480                    break;
1481                }
1482            }
1483        } else {
1484            if (strcmp(string[i], saveString) == 0) {
1485                isSame = 1;
1486            } else {
1487                saveFlag = 0;
1488                for (j = i + 1; j < k; j++) {
1489                    if (strcmp(string[i], string[j]) == 0) {
1490                        savePoint = i;
1491                        strcpy(saveString, string[i]);
1492                        saveFlag = 1;
1493                        break;
1494                    }
1495                }
1496            }
1497        }
1498        /* Randomize choice for don't cares. */
1499        for (j = 0; j < n; j++) {
1500            if (string[i][indices[j]] == '2')
1501                string[i][indices[j]] = (Cudd_Random() & 0x20) ? '1' : '0';
1502        }
1503
1504        while (isSame) {
1505            isSame = 0;
1506            for (j = savePoint; j < i; j++) {
1507                if (strcmp(string[i], string[j]) == 0) {
1508                    isSame = 1;
1509                    break;
1510                }
1511            }
1512            if (isSame) {
1513                strcpy(string[i], saveString);
1514                /* Randomize choice for don't cares. */
1515                for (j = 0; j < n; j++) {
1516                    if (string[i][indices[j]] == '2') 
1517                        string[i][indices[j]] = (Cudd_Random() & 0x20) ?
1518                            '1' : '0';
1519                }
1520            }
1521        }
1522
1523        old[i] = Cudd_ReadOne(dd);
1524        cuddRef(old[i]);
1525
1526        for (j = 0; j < n; j++) {
1527            if (string[i][indices[j]] == '0') {
1528                neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j]));
1529            } else {
1530                neW = Cudd_bddAnd(dd,old[i],vars[j]);
1531            }
1532            if (neW == NULL) {
1533                FREE(saveString);
1534                for (l = 0; l < k; l++)
1535                    FREE(string[l]);
1536                FREE(string);
1537                FREE(indices);
1538                for (l = 0; l <= i; l++)
1539                    Cudd_RecursiveDeref(dd,old[l]);
1540                FREE(old);
1541                return(NULL);
1542            }
1543            cuddRef(neW);
1544            Cudd_RecursiveDeref(dd,old[i]);
1545            old[i] = neW;
1546        }
1547
1548        /* Test. */
1549        if (!Cudd_bddLeq(dd,old[i],f)) {
1550            FREE(saveString);
1551            for (l = 0; l < k; l++)
1552                FREE(string[l]);
1553            FREE(string);
1554            FREE(indices);
1555            for (l = 0; l <= i; l++)
1556                Cudd_RecursiveDeref(dd,old[l]);
1557            FREE(old);
1558            return(NULL);
1559        }
1560    }
1561
1562    FREE(saveString);
1563    for (i = 0; i < k; i++) {
1564        cuddDeref(old[i]);
1565        FREE(string[i]);
1566    }
1567    FREE(string);
1568    FREE(indices);
1569    return(old);
1570
1571}  /* end of Cudd_bddPickArbitraryMinterms */
1572
1573
1574/**Function********************************************************************
1575
1576  Synopsis    [Extracts a subset from a BDD.]
1577
1578  Description [Extracts a subset from a BDD in the following procedure.
1579  1. Compute the weight for each mask variable by counting the number of
1580     minterms for both positive and negative cofactors of the BDD with
1581     respect to each mask variable. (weight = #positive - #negative)
1582  2. Find a representative cube of the BDD by using the weight. From the
1583     top variable of the BDD, for each variable, if the weight is greater
1584     than 0.0, choose THEN branch, othereise ELSE branch, until meeting
1585     the constant 1.
1586  3. Quantify out the variables not in maskVars from the representative
1587     cube and if a variable in maskVars is don't care, replace the
1588     variable with a constant(1 or 0) depending on the weight.
1589  4. Make a subset of the BDD by multiplying with the modified cube.]
1590
1591  SideEffects [None]
1592
1593  SeeAlso     []
1594
1595******************************************************************************/
1596DdNode *
1597Cudd_SubsetWithMaskVars(
1598  DdManager * dd /* manager */,
1599  DdNode * f /* function from which to pick a cube */,
1600  DdNode ** vars /* array of variables */,
1601  int  nvars /* size of <code>vars</code> */,
1602  DdNode ** maskVars /* array of variables */,
1603  int  mvars /* size of <code>maskVars</code> */)
1604{
1605    double      *weight;
1606    char        *string;
1607    int         i, size;
1608    int         *indices, *mask;
1609    int         result;
1610    DdNode      *zero, *cube, *newCube, *subset;
1611    DdNode      *cof;
1612
1613    DdNode      *support;
1614    support = Cudd_Support(dd,f);
1615    cuddRef(support);
1616    Cudd_RecursiveDeref(dd,support);
1617
1618    zero = Cudd_Not(dd->one);
1619    size = dd->size;
1620   
1621    weight = ALLOC(double,size);
1622    if (weight == NULL) {
1623        dd->errorCode = CUDD_MEMORY_OUT;
1624        return(NULL);
1625    }
1626    for (i = 0; i < size; i++) {
1627        weight[i] = 0.0;
1628    }
1629    for (i = 0; i < mvars; i++) {
1630        cof = Cudd_Cofactor(dd, f, maskVars[i]);
1631        cuddRef(cof);
1632        weight[i] = Cudd_CountMinterm(dd, cof, nvars);
1633        Cudd_RecursiveDeref(dd,cof);
1634
1635        cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i]));
1636        cuddRef(cof);
1637        weight[i] -= Cudd_CountMinterm(dd, cof, nvars);
1638        Cudd_RecursiveDeref(dd,cof);
1639    }
1640
1641    string = ALLOC(char, size + 1);
1642    if (string == NULL) {
1643        dd->errorCode = CUDD_MEMORY_OUT;
1644        return(NULL);
1645    }
1646    mask = ALLOC(int, size);
1647    if (mask == NULL) {
1648        dd->errorCode = CUDD_MEMORY_OUT;
1649        FREE(string);
1650        return(NULL);
1651    }
1652    for (i = 0; i < size; i++) {
1653        string[i] = '2';
1654        mask[i] = 0;
1655    }
1656    string[size] = '\0';
1657    indices = ALLOC(int,nvars);
1658    if (indices == NULL) {
1659        dd->errorCode = CUDD_MEMORY_OUT;
1660        FREE(string);
1661        FREE(mask);
1662        return(NULL);
1663    }
1664    for (i = 0; i < nvars; i++) {
1665        indices[i] = vars[i]->index;
1666    }
1667
1668    result = ddPickRepresentativeCube(dd,f,nvars,weight,string);
1669    if (result == 0) {
1670        FREE(string);
1671        FREE(mask);
1672        FREE(indices);
1673        return(NULL);
1674    }
1675
1676    cube = Cudd_ReadOne(dd);
1677    cuddRef(cube);
1678    zero = Cudd_Not(Cudd_ReadOne(dd));
1679    for (i = 0; i < nvars; i++) {
1680        if (string[indices[i]] == '0') {
1681            newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
1682        } else if (string[indices[i]] == '1') {
1683            newCube = Cudd_bddIte(dd,cube,vars[i],zero);
1684        } else
1685            continue;
1686        if (newCube == NULL) {
1687            FREE(string);
1688            FREE(mask);
1689            FREE(indices);
1690            Cudd_RecursiveDeref(dd,cube);
1691            return(NULL);
1692        }
1693        cuddRef(newCube);
1694        Cudd_RecursiveDeref(dd,cube);
1695        cube = newCube;
1696    }
1697    Cudd_RecursiveDeref(dd,cube);
1698
1699    for (i = 0; i < mvars; i++) {
1700        mask[maskVars[i]->index] = 1;
1701    }
1702    for (i = 0; i < nvars; i++) {
1703        if (mask[indices[i]]) {
1704            if (string[indices[i]] == '2') {
1705                if (weight[indices[i]] >= 0.0)
1706                    string[indices[i]] = '1';
1707                else
1708                    string[indices[i]] = '0';
1709            }
1710        } else {
1711            string[indices[i]] = '2';
1712        }
1713    }
1714
1715    cube = Cudd_ReadOne(dd);
1716    cuddRef(cube);
1717    zero = Cudd_Not(Cudd_ReadOne(dd));
1718
1719    /* Build result BDD. */
1720    for (i = 0; i < nvars; i++) {
1721        if (string[indices[i]] == '0') {
1722            newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
1723        } else if (string[indices[i]] == '1') {
1724            newCube = Cudd_bddIte(dd,cube,vars[i],zero);
1725        } else
1726            continue;
1727        if (newCube == NULL) {
1728            FREE(string);
1729            FREE(mask);
1730            FREE(indices);
1731            Cudd_RecursiveDeref(dd,cube);
1732            return(NULL);
1733        }
1734        cuddRef(newCube);
1735        Cudd_RecursiveDeref(dd,cube);
1736        cube = newCube;
1737    }
1738
1739    subset = Cudd_bddAnd(dd,f,cube);
1740    cuddRef(subset);
1741    Cudd_RecursiveDeref(dd,cube);
1742
1743    /* Test. */
1744    if (Cudd_bddLeq(dd,subset,f)) {
1745        cuddDeref(subset);
1746    } else {
1747        Cudd_RecursiveDeref(dd,subset);
1748        subset = NULL;
1749    }
1750
1751    FREE(string);
1752    FREE(mask);
1753    FREE(indices);
1754    FREE(weight);
1755    return(subset);
1756
1757} /* end of Cudd_SubsetWithMaskVars */
1758
1759
1760/**Function********************************************************************
1761
1762  Synopsis    [Finds the first cube of a decision diagram.]
1763
1764  Description [Defines an iterator on the onset of a decision diagram
1765  and finds its first cube. Returns a generator that contains the
1766  information necessary to continue the enumeration if successful; NULL
1767  otherwise.<p>
1768  A cube is represented as an array of literals, which are integers in
1769  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
1770  uncomplemented literal, and 2 stands for don't care. The enumeration
1771  produces a disjoint cover of the function associated with the diagram.
1772  The size of the array equals the number of variables in the manager at
1773  the time Cudd_FirstCube is called.<p>
1774  For each cube, a value is also returned. This value is always 1 for a
1775  BDD, while it may be different from 1 for an ADD.
1776  For BDDs, the offset is the set of cubes whose value is the logical zero.
1777  For ADDs, the offset is the set of cubes whose value is the
1778  background value. The cubes of the offset are not enumerated.]
1779
1780  SideEffects [The first cube and its value are returned as side effects.]
1781
1782  SeeAlso     [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty
1783  Cudd_FirstNode]
1784
1785******************************************************************************/
1786DdGen *
1787Cudd_FirstCube(
1788  DdManager * dd,
1789  DdNode * f,
1790  int ** cube,
1791  CUDD_VALUE_TYPE * value)
1792{
1793    DdGen *gen;
1794    DdNode *top, *treg, *next, *nreg, *prev, *preg;
1795    int i;
1796    int nvars;
1797
1798    /* Sanity Check. */
1799    if (dd == NULL || f == NULL) return(NULL);
1800
1801    /* Allocate generator an initialize it. */
1802    gen = ALLOC(DdGen,1);
1803    if (gen == NULL) {
1804        dd->errorCode = CUDD_MEMORY_OUT;
1805        return(NULL);
1806    }
1807
1808    gen->manager = dd;
1809    gen->type = CUDD_GEN_CUBES;
1810    gen->status = CUDD_GEN_EMPTY;
1811    gen->gen.cubes.cube = NULL;
1812    gen->gen.cubes.value = DD_ZERO_VAL;
1813    gen->stack.sp = 0;
1814    gen->stack.stack = NULL;
1815    gen->node = NULL;
1816
1817    nvars = dd->size;
1818    gen->gen.cubes.cube = ALLOC(int,nvars);
1819    if (gen->gen.cubes.cube == NULL) {
1820        dd->errorCode = CUDD_MEMORY_OUT;
1821        FREE(gen);
1822        return(NULL);
1823    }
1824    for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
1825
1826    /* The maximum stack depth is one plus the number of variables.
1827    ** because a path may have nodes at all levels, including the
1828    ** constant level.
1829    */
1830    gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
1831    if (gen->stack.stack == NULL) {
1832        dd->errorCode = CUDD_MEMORY_OUT;
1833        FREE(gen->gen.cubes.cube);
1834        FREE(gen);
1835        return(NULL);
1836    }
1837    for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
1838
1839    /* Find the first cube of the onset. */
1840    gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
1841
1842    while (1) {
1843        top = gen->stack.stack[gen->stack.sp-1];
1844        treg = Cudd_Regular(top);
1845        if (!cuddIsConstant(treg)) {
1846            /* Take the else branch first. */
1847            gen->gen.cubes.cube[treg->index] = 0;
1848            next = cuddE(treg);
1849            if (top != treg) next = Cudd_Not(next);
1850            gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
1851        } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
1852            /* Backtrack */
1853            while (1) {
1854                if (gen->stack.sp == 1) {
1855                    /* The current node has no predecessor. */
1856                    gen->status = CUDD_GEN_EMPTY;
1857                    gen->stack.sp--;
1858                    goto done;
1859                }
1860                prev = gen->stack.stack[gen->stack.sp-2];
1861                preg = Cudd_Regular(prev);
1862                nreg = cuddT(preg);
1863                if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1864                if (next != top) { /* follow the then branch next */
1865                    gen->gen.cubes.cube[preg->index] = 1;
1866                    gen->stack.stack[gen->stack.sp-1] = next;
1867                    break;
1868                }
1869                /* Pop the stack and try again. */
1870                gen->gen.cubes.cube[preg->index] = 2;
1871                gen->stack.sp--;
1872                top = gen->stack.stack[gen->stack.sp-1];
1873                treg = Cudd_Regular(top);
1874            }
1875        } else {
1876            gen->status = CUDD_GEN_NONEMPTY;
1877            gen->gen.cubes.value = cuddV(top);
1878            goto done;
1879        }
1880    }
1881
1882done:
1883    *cube = gen->gen.cubes.cube;
1884    *value = gen->gen.cubes.value;
1885    return(gen);
1886
1887} /* end of Cudd_FirstCube */
1888
1889
1890/**Function********************************************************************
1891
1892  Synopsis    [Generates the next cube of a decision diagram onset.]
1893
1894  Description [Generates the next cube of a decision diagram onset,
1895  using generator gen. Returns 0 if the enumeration is completed; 1
1896  otherwise.]
1897
1898  SideEffects [The cube and its value are returned as side effects. The
1899  generator is modified.]
1900
1901  SeeAlso     [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty
1902  Cudd_NextNode]
1903
1904******************************************************************************/
1905int
1906Cudd_NextCube(
1907  DdGen * gen,
1908  int ** cube,
1909  CUDD_VALUE_TYPE * value)
1910{
1911    DdNode *top, *treg, *next, *nreg, *prev, *preg;
1912    DdManager *dd = gen->manager;
1913
1914    /* Backtrack from previously reached terminal node. */
1915    while (1) {
1916        if (gen->stack.sp == 1) {
1917            /* The current node has no predecessor. */
1918            gen->status = CUDD_GEN_EMPTY;
1919            gen->stack.sp--;
1920            goto done;
1921        }
1922        top = gen->stack.stack[gen->stack.sp-1];
1923        treg = Cudd_Regular(top);
1924        prev = gen->stack.stack[gen->stack.sp-2];
1925        preg = Cudd_Regular(prev);
1926        nreg = cuddT(preg);
1927        if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1928        if (next != top) { /* follow the then branch next */
1929            gen->gen.cubes.cube[preg->index] = 1;
1930            gen->stack.stack[gen->stack.sp-1] = next;
1931            break;
1932        }
1933        /* Pop the stack and try again. */
1934        gen->gen.cubes.cube[preg->index] = 2;
1935        gen->stack.sp--;
1936    }
1937
1938    while (1) {
1939        top = gen->stack.stack[gen->stack.sp-1];
1940        treg = Cudd_Regular(top);
1941        if (!cuddIsConstant(treg)) {
1942            /* Take the else branch first. */
1943            gen->gen.cubes.cube[treg->index] = 0;
1944            next = cuddE(treg);
1945            if (top != treg) next = Cudd_Not(next);
1946            gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
1947        } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
1948            /* Backtrack */
1949            while (1) {
1950                if (gen->stack.sp == 1) {
1951                    /* The current node has no predecessor. */
1952                    gen->status = CUDD_GEN_EMPTY;
1953                    gen->stack.sp--;
1954                    goto done;
1955                }
1956                prev = gen->stack.stack[gen->stack.sp-2];
1957                preg = Cudd_Regular(prev);
1958                nreg = cuddT(preg);
1959                if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1960                if (next != top) { /* follow the then branch next */
1961                    gen->gen.cubes.cube[preg->index] = 1;
1962                    gen->stack.stack[gen->stack.sp-1] = next;
1963                    break;
1964                }
1965                /* Pop the stack and try again. */
1966                gen->gen.cubes.cube[preg->index] = 2;
1967                gen->stack.sp--;
1968                top = gen->stack.stack[gen->stack.sp-1];
1969                treg = Cudd_Regular(top);
1970            }
1971        } else {
1972            gen->status = CUDD_GEN_NONEMPTY;
1973            gen->gen.cubes.value = cuddV(top);
1974            goto done;
1975        }
1976    }
1977
1978done:
1979    if (gen->status == CUDD_GEN_EMPTY) return(0);
1980    *cube = gen->gen.cubes.cube;
1981    *value = gen->gen.cubes.value;
1982    return(1);
1983
1984} /* end of Cudd_NextCube */
1985
1986
1987/**Function********************************************************************
1988
1989  Synopsis    [Finds the first prime of a Boolean function.]
1990
1991  Description [Defines an iterator on a pair of BDDs describing a
1992  (possibly incompletely specified) Boolean functions and finds the
1993  first cube of a cover of the function.  Returns a generator
1994  that contains the information necessary to continue the enumeration
1995  if successful; NULL otherwise.<p>
1996
1997  The two argument BDDs are the lower and upper bounds of an interval.
1998  It is a mistake to call this function with a lower bound that is not
1999  less than or equal to the upper bound.<p>
2000
2001  A cube is represented as an array of literals, which are integers in
2002  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
2003  uncomplemented literal, and 2 stands for don't care. The enumeration
2004  produces a prime and irredundant cover of the function associated
2005  with the two BDDs.  The size of the array equals the number of
2006  variables in the manager at the time Cudd_FirstCube is called.<p>
2007
2008  This iterator can only be used on BDDs.]
2009
2010  SideEffects [The first cube is returned as side effect.]
2011
2012  SeeAlso     [Cudd_ForeachPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty
2013  Cudd_FirstCube Cudd_FirstNode]
2014
2015******************************************************************************/
2016DdGen *
2017Cudd_FirstPrime(
2018  DdManager *dd,
2019  DdNode *l,
2020  DdNode *u,
2021  int **cube)
2022{
2023    DdGen *gen;
2024    DdNode *implicant, *prime, *tmp;
2025    int length, result;
2026
2027    /* Sanity Check. */
2028    if (dd == NULL || l == NULL || u == NULL) return(NULL);
2029
2030    /* Allocate generator an initialize it. */
2031    gen = ALLOC(DdGen,1);
2032    if (gen == NULL) {
2033        dd->errorCode = CUDD_MEMORY_OUT;
2034        return(NULL);
2035    }
2036
2037    gen->manager = dd;
2038    gen->type = CUDD_GEN_PRIMES;
2039    gen->status = CUDD_GEN_EMPTY;
2040    gen->gen.primes.cube = NULL;
2041    gen->gen.primes.ub = u;
2042    gen->stack.sp = 0;
2043    gen->stack.stack = NULL;
2044    gen->node = l;
2045    cuddRef(l);
2046
2047    gen->gen.primes.cube = ALLOC(int,dd->size);
2048    if (gen->gen.primes.cube == NULL) {
2049        dd->errorCode = CUDD_MEMORY_OUT;
2050        FREE(gen);
2051        return(NULL);
2052    }
2053
2054    if (gen->node == Cudd_ReadLogicZero(dd)) {
2055        gen->status = CUDD_GEN_EMPTY;
2056    } else {
2057        implicant = Cudd_LargestCube(dd,gen->node,&length);
2058        if (implicant == NULL) {
2059            Cudd_RecursiveDeref(dd,gen->node);
2060            FREE(gen->gen.primes.cube);
2061            FREE(gen);
2062            return(NULL);
2063        }
2064        cuddRef(implicant);
2065        prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
2066        if (prime == NULL) {
2067            Cudd_RecursiveDeref(dd,gen->node);
2068            Cudd_RecursiveDeref(dd,implicant);
2069            FREE(gen->gen.primes.cube);
2070            FREE(gen);
2071            return(NULL);
2072        }
2073        cuddRef(prime);
2074        Cudd_RecursiveDeref(dd,implicant);
2075        tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
2076        if (tmp == NULL) {
2077            Cudd_RecursiveDeref(dd,gen->node);
2078            Cudd_RecursiveDeref(dd,prime);
2079            FREE(gen->gen.primes.cube);
2080            FREE(gen);
2081            return(NULL);
2082        }
2083        cuddRef(tmp);
2084        Cudd_RecursiveDeref(dd,gen->node);
2085        gen->node = tmp;
2086        result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
2087        if (result == 0) {
2088            Cudd_RecursiveDeref(dd,gen->node);
2089            Cudd_RecursiveDeref(dd,prime);
2090            FREE(gen->gen.primes.cube);
2091            FREE(gen);
2092            return(NULL);
2093        }
2094        Cudd_RecursiveDeref(dd,prime);
2095        gen->status = CUDD_GEN_NONEMPTY;
2096    }
2097    *cube = gen->gen.primes.cube;
2098    return(gen);
2099
2100} /* end of Cudd_FirstPrime */
2101
2102
2103/**Function********************************************************************
2104
2105  Synopsis    [Generates the next prime of a Boolean function.]
2106
2107  Description [Generates the next cube of a Boolean function,
2108  using generator gen. Returns 0 if the enumeration is completed; 1
2109  otherwise.]
2110
2111  SideEffects [The cube and is returned as side effects. The
2112  generator is modified.]
2113
2114  SeeAlso     [Cudd_ForeachPrime Cudd_FirstPrime Cudd_GenFree Cudd_IsGenEmpty
2115  Cudd_NextCube Cudd_NextNode]
2116
2117******************************************************************************/
2118int
2119Cudd_NextPrime(
2120  DdGen *gen,
2121  int **cube)
2122{
2123    DdNode *implicant, *prime, *tmp;
2124    DdManager *dd = gen->manager;
2125    int length, result;
2126
2127    if (gen->node == Cudd_ReadLogicZero(dd)) {
2128        gen->status = CUDD_GEN_EMPTY;
2129    } else {
2130        implicant = Cudd_LargestCube(dd,gen->node,&length);
2131        if (implicant == NULL) {
2132            gen->status = CUDD_GEN_EMPTY;
2133            return(0);
2134        }
2135        cuddRef(implicant);
2136        prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
2137        if (prime == NULL) {
2138            Cudd_RecursiveDeref(dd,implicant);
2139            gen->status = CUDD_GEN_EMPTY;
2140            return(0);
2141        }
2142        cuddRef(prime);
2143        Cudd_RecursiveDeref(dd,implicant);
2144        tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
2145        if (tmp == NULL) {
2146            Cudd_RecursiveDeref(dd,prime);
2147            gen->status = CUDD_GEN_EMPTY;
2148            return(0);
2149        }
2150        cuddRef(tmp);
2151        Cudd_RecursiveDeref(dd,gen->node);
2152        gen->node = tmp;
2153        result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
2154        if (result == 0) {
2155            Cudd_RecursiveDeref(dd,prime);
2156            gen->status = CUDD_GEN_EMPTY;
2157            return(0);
2158        }
2159        Cudd_RecursiveDeref(dd,prime);
2160        gen->status = CUDD_GEN_NONEMPTY;
2161    }
2162    if (gen->status == CUDD_GEN_EMPTY) return(0);
2163    *cube = gen->gen.primes.cube;
2164    return(1);
2165
2166} /* end of Cudd_NextPrime */
2167
2168
2169/**Function********************************************************************
2170
2171  Synopsis    [Computes the cube of an array of BDD variables.]
2172
2173  Description [Computes the cube of an array of BDD variables. If
2174  non-null, the phase argument indicates which literal of each
2175  variable should appear in the cube. If phase\[i\] is nonzero, then the
2176  positive literal is used. If phase is NULL, the cube is positive unate.
2177  Returns a pointer to the result if successful; NULL otherwise.]
2178
2179  SideEffects [None]
2180
2181  SeeAlso     [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd]
2182
2183******************************************************************************/
2184DdNode *
2185Cudd_bddComputeCube(
2186  DdManager * dd,
2187  DdNode ** vars,
2188  int * phase,
2189  int  n)
2190{
2191    DdNode      *cube;
2192    DdNode      *fn;
2193    int         i;
2194
2195    cube = DD_ONE(dd);
2196    cuddRef(cube);
2197
2198    for (i = n - 1; i >= 0; i--) {
2199        if (phase == NULL || phase[i] != 0) {
2200            fn = Cudd_bddAnd(dd,vars[i],cube);
2201        } else {
2202            fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube);
2203        }
2204        if (fn == NULL) {
2205            Cudd_RecursiveDeref(dd,cube);
2206            return(NULL);
2207        }
2208        cuddRef(fn);
2209        Cudd_RecursiveDeref(dd,cube);
2210        cube = fn;
2211    }
2212    cuddDeref(cube);
2213
2214    return(cube);
2215
2216}  /* end of Cudd_bddComputeCube */
2217
2218
2219/**Function********************************************************************
2220
2221  Synopsis    [Computes the cube of an array of ADD variables.]
2222
2223  Description [Computes the cube of an array of ADD variables.  If
2224  non-null, the phase argument indicates which literal of each
2225  variable should appear in the cube. If phase\[i\] is nonzero, then the
2226  positive literal is used. If phase is NULL, the cube is positive unate.
2227  Returns a pointer to the result if successful; NULL otherwise.]
2228
2229  SideEffects [none]
2230
2231  SeeAlso     [Cudd_bddComputeCube]
2232
2233******************************************************************************/
2234DdNode *
2235Cudd_addComputeCube(
2236  DdManager * dd,
2237  DdNode ** vars,
2238  int * phase,
2239  int  n)
2240{
2241    DdNode      *cube, *zero;
2242    DdNode      *fn;
2243    int         i;
2244
2245    cube = DD_ONE(dd);
2246    cuddRef(cube);
2247    zero = DD_ZERO(dd);
2248
2249    for (i = n - 1; i >= 0; i--) {
2250        if (phase == NULL || phase[i] != 0) {
2251            fn = Cudd_addIte(dd,vars[i],cube,zero);
2252        } else {
2253            fn = Cudd_addIte(dd,vars[i],zero,cube);
2254        }
2255        if (fn == NULL) {
2256            Cudd_RecursiveDeref(dd,cube);
2257            return(NULL);
2258        }
2259        cuddRef(fn);
2260        Cudd_RecursiveDeref(dd,cube);
2261        cube = fn;
2262    }
2263    cuddDeref(cube);
2264
2265    return(cube);
2266
2267} /* end of Cudd_addComputeCube */
2268
2269
2270/**Function********************************************************************
2271
2272  Synopsis    [Builds the BDD of a cube from a positional array.]
2273
2274  Description [Builds a cube from a positional array.  The array must
2275  have one integer entry for each BDD variable.  If the i-th entry is
2276  1, the variable of index i appears in true form in the cube; If the
2277  i-th entry is 0, the variable of index i appears complemented in the
2278  cube; otherwise the variable does not appear in the cube.  Returns a
2279  pointer to the BDD for the cube if successful; NULL otherwise.]
2280
2281  SideEffects [None]
2282
2283  SeeAlso     [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray]
2284
2285******************************************************************************/
2286DdNode *
2287Cudd_CubeArrayToBdd(
2288  DdManager *dd,
2289  int *array)
2290{
2291    DdNode *cube, *var, *tmp;
2292    int i;
2293    int size = Cudd_ReadSize(dd);
2294
2295    cube = DD_ONE(dd);
2296    cuddRef(cube);
2297    for (i = size - 1; i >= 0; i--) {
2298        if ((array[i] & ~1) == 0) {
2299            var = Cudd_bddIthVar(dd,i);
2300            tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0));
2301            if (tmp == NULL) {
2302                Cudd_RecursiveDeref(dd,cube);
2303                return(NULL);
2304            }
2305            cuddRef(tmp);
2306            Cudd_RecursiveDeref(dd,cube);
2307            cube = tmp;
2308        }
2309    }
2310    cuddDeref(cube);
2311    return(cube);
2312
2313} /* end of Cudd_CubeArrayToBdd */
2314
2315
2316/**Function********************************************************************
2317
2318  Synopsis    [Builds a positional array from the BDD of a cube.]
2319
2320  Description [Builds a positional array from the BDD of a cube.
2321  Array must have one entry for each BDD variable.  The positional
2322  array has 1 in i-th position if the variable of index i appears in
2323  true form in the cube; it has 0 in i-th position if the variable of
2324  index i appears in complemented form in the cube; finally, it has 2
2325  in i-th position if the variable of index i does not appear in the
2326  cube.  Returns 1 if successful (the BDD is indeed a cube); 0
2327  otherwise.]
2328
2329  SideEffects [The result is in the array passed by reference.]
2330
2331  SeeAlso     [Cudd_CubeArrayToBdd]
2332
2333******************************************************************************/
2334int
2335Cudd_BddToCubeArray(
2336  DdManager *dd,
2337  DdNode *cube,
2338  int *array)
2339{
2340    DdNode *scan, *t, *e;
2341    int i;
2342    int size = Cudd_ReadSize(dd);
2343    DdNode *zero = Cudd_Not(DD_ONE(dd));
2344
2345    for (i = size-1; i >= 0; i--) {
2346        array[i] = 2;
2347    }
2348    scan = cube;
2349    while (!Cudd_IsConstant(scan)) {
2350        int index = Cudd_Regular(scan)->index;
2351        cuddGetBranches(scan,&t,&e);
2352        if (t == zero) {
2353            array[index] = 0;
2354            scan = e;
2355        } else if (e == zero) {
2356            array[index] = 1;
2357            scan = t;
2358        } else {
2359            return(0);  /* cube is not a cube */
2360        }
2361    }
2362    if (scan == zero) {
2363        return(0);
2364    } else {
2365        return(1);
2366    }
2367
2368} /* end of Cudd_BddToCubeArray */
2369
2370
2371/**Function********************************************************************
2372
2373  Synopsis    [Finds the first node of a decision diagram.]
2374
2375  Description [Defines an iterator on the nodes of a decision diagram
2376  and finds its first node. Returns a generator that contains the
2377  information necessary to continue the enumeration if successful;
2378  NULL otherwise.  The nodes are enumerated in a reverse topological
2379  order, so that a node is always preceded in the enumeration by its
2380  descendants.]
2381
2382  SideEffects [The first node is returned as a side effect.]
2383
2384  SeeAlso     [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty
2385  Cudd_FirstCube]
2386
2387******************************************************************************/
2388DdGen *
2389Cudd_FirstNode(
2390  DdManager * dd,
2391  DdNode * f,
2392  DdNode ** node)
2393{
2394    DdGen *gen;
2395    int size;
2396
2397    /* Sanity Check. */
2398    if (dd == NULL || f == NULL) return(NULL);
2399
2400    /* Allocate generator an initialize it. */
2401    gen = ALLOC(DdGen,1);
2402    if (gen == NULL) {
2403        dd->errorCode = CUDD_MEMORY_OUT;
2404        return(NULL);
2405    }
2406
2407    gen->manager = dd;
2408    gen->type = CUDD_GEN_NODES;
2409    gen->status = CUDD_GEN_EMPTY;
2410    gen->stack.sp = 0;
2411    gen->node = NULL;
2412
2413    /* Collect all the nodes on the generator stack for later perusal. */
2414    gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
2415    if (gen->stack.stack == NULL) {
2416        FREE(gen);
2417        dd->errorCode = CUDD_MEMORY_OUT;
2418        return(NULL);
2419    }
2420    gen->gen.nodes.size = size;
2421
2422    /* Find the first node. */
2423    if (gen->stack.sp < gen->gen.nodes.size) {
2424        gen->status = CUDD_GEN_NONEMPTY;
2425        gen->node = gen->stack.stack[gen->stack.sp];
2426        *node = gen->node;
2427    }
2428
2429    return(gen);
2430
2431} /* end of Cudd_FirstNode */
2432
2433
2434/**Function********************************************************************
2435
2436  Synopsis    [Finds the next node of a decision diagram.]
2437
2438  Description [Finds the node of a decision diagram, using generator
2439  gen. Returns 0 if the enumeration is completed; 1 otherwise.]
2440
2441  SideEffects [The next node is returned as a side effect.]
2442
2443  SeeAlso     [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty
2444  Cudd_NextCube]
2445
2446******************************************************************************/
2447int
2448Cudd_NextNode(
2449  DdGen * gen,
2450  DdNode ** node)
2451{
2452    /* Find the next node. */
2453    gen->stack.sp++;
2454    if (gen->stack.sp < gen->gen.nodes.size) {
2455        gen->node = gen->stack.stack[gen->stack.sp];
2456        *node = gen->node;
2457        return(1);
2458    } else {
2459        gen->status = CUDD_GEN_EMPTY;
2460        return(0);
2461    }
2462
2463} /* end of Cudd_NextNode */
2464
2465
2466/**Function********************************************************************
2467
2468  Synopsis    [Frees a CUDD generator.]
2469
2470  Description [Frees a CUDD generator. Always returns 0, so that it can
2471  be used in mis-like foreach constructs.]
2472
2473  SideEffects [None]
2474
2475  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2476  Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty]
2477
2478******************************************************************************/
2479int
2480Cudd_GenFree(
2481  DdGen * gen)
2482{
2483    if (gen == NULL) return(0);
2484    switch (gen->type) {
2485    case CUDD_GEN_CUBES:
2486    case CUDD_GEN_ZDD_PATHS:
2487        FREE(gen->gen.cubes.cube);
2488        FREE(gen->stack.stack);
2489        break;
2490    case CUDD_GEN_PRIMES:
2491        FREE(gen->gen.primes.cube);
2492        Cudd_RecursiveDeref(gen->manager,gen->node);
2493        break;
2494    case CUDD_GEN_NODES:
2495        FREE(gen->stack.stack);
2496        break;
2497    default:
2498        return(0);
2499    }
2500    FREE(gen);
2501    return(0);
2502
2503} /* end of Cudd_GenFree */
2504
2505
2506/**Function********************************************************************
2507
2508  Synopsis    [Queries the status of a generator.]
2509
2510  Description [Queries the status of a generator. Returns 1 if the
2511  generator is empty or NULL; 0 otherswise.]
2512
2513  SideEffects [None]
2514
2515  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2516  Cudd_FirstNode Cudd_NextNode Cudd_GenFree]
2517
2518******************************************************************************/
2519int
2520Cudd_IsGenEmpty(
2521  DdGen * gen)
2522{
2523    if (gen == NULL) return(1);
2524    return(gen->status == CUDD_GEN_EMPTY);
2525
2526} /* end of Cudd_IsGenEmpty */
2527
2528
2529/**Function********************************************************************
2530
2531  Synopsis    [Builds a cube of BDD variables from an array of indices.]
2532
2533  Description [Builds a cube of BDD variables from an array of indices.
2534  Returns a pointer to the result if successful; NULL otherwise.]
2535
2536  SideEffects [None]
2537
2538  SeeAlso     [Cudd_bddComputeCube Cudd_CubeArrayToBdd]
2539
2540******************************************************************************/
2541DdNode *
2542Cudd_IndicesToCube(
2543  DdManager * dd,
2544  int * array,
2545  int  n)
2546{
2547    DdNode *cube, *tmp;
2548    int i;
2549
2550    cube = DD_ONE(dd);
2551    cuddRef(cube);
2552    for (i = n - 1; i >= 0; i--) {
2553        tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube);
2554        if (tmp == NULL) {
2555            Cudd_RecursiveDeref(dd,cube);
2556            return(NULL);
2557        }
2558        cuddRef(tmp);
2559        Cudd_RecursiveDeref(dd,cube);
2560        cube = tmp;
2561    }
2562
2563    cuddDeref(cube);
2564    return(cube);
2565
2566} /* end of Cudd_IndicesToCube */
2567
2568
2569/**Function********************************************************************
2570
2571  Synopsis    [Prints the package version number.]
2572
2573  Description []
2574
2575  SideEffects [None]
2576
2577  SeeAlso     []
2578
2579******************************************************************************/
2580void
2581Cudd_PrintVersion(
2582  FILE * fp)
2583{
2584    (void) fprintf(fp, "%s\n", CUDD_VERSION);
2585
2586} /* end of Cudd_PrintVersion */
2587
2588
2589/**Function********************************************************************
2590
2591  Synopsis    [Computes the average distance between adjacent nodes.]
2592
2593  Description [Computes the average distance between adjacent nodes in
2594  the manager. Adjacent nodes are node pairs such that the second node
2595  is the then child, else child, or next node in the collision list.]
2596
2597  SideEffects [None]
2598
2599  SeeAlso     []
2600
2601******************************************************************************/
2602double
2603Cudd_AverageDistance(
2604  DdManager * dd)
2605{
2606    double tetotal, nexttotal;
2607    double tesubtotal, nextsubtotal;
2608    double temeasured, nextmeasured;
2609    int i, j;
2610    int slots, nvars;
2611    long diff;
2612    DdNode *scan;
2613    DdNodePtr *nodelist;
2614    DdNode *sentinel = &(dd->sentinel);
2615
2616    nvars = dd->size;
2617    if (nvars == 0) return(0.0);
2618
2619    /* Initialize totals. */
2620    tetotal = 0.0;
2621    nexttotal = 0.0;
2622    temeasured = 0.0;
2623    nextmeasured = 0.0;
2624
2625    /* Scan the variable subtables. */
2626    for (i = 0; i < nvars; i++) {
2627        nodelist = dd->subtables[i].nodelist;
2628        tesubtotal = 0.0;
2629        nextsubtotal = 0.0;
2630        slots = dd->subtables[i].slots;
2631        for (j = 0; j < slots; j++) {
2632            scan = nodelist[j];
2633            while (scan != sentinel) {
2634                diff = (long) scan - (long) cuddT(scan);
2635                tesubtotal += (double) ddAbs(diff);
2636                diff = (long) scan - (long) Cudd_Regular(cuddE(scan));
2637                tesubtotal += (double) ddAbs(diff);
2638                temeasured += 2.0;
2639                if (scan->next != NULL) {
2640                    diff = (long) scan - (long) scan->next;
2641                    nextsubtotal += (double) ddAbs(diff);
2642                    nextmeasured += 1.0;
2643                }
2644                scan = scan->next;
2645            }
2646        }
2647        tetotal += tesubtotal;
2648        nexttotal += nextsubtotal;
2649    }
2650
2651    /* Scan the constant table. */
2652    nodelist = dd->constants.nodelist;
2653    nextsubtotal = 0.0;
2654    slots = dd->constants.slots;
2655    for (j = 0; j < slots; j++) {
2656        scan = nodelist[j];
2657        while (scan != NULL) {
2658            if (scan->next != NULL) {
2659                diff = (long) scan - (long) scan->next;
2660                nextsubtotal += (double) ddAbs(diff);
2661                nextmeasured += 1.0;
2662            }
2663            scan = scan->next;
2664        }
2665    }
2666    nexttotal += nextsubtotal;
2667
2668    return((tetotal + nexttotal) / (temeasured + nextmeasured));
2669
2670} /* end of Cudd_AverageDistance */
2671
2672
2673/**Function********************************************************************
2674
2675  Synopsis    [Portable random number generator.]
2676
2677  Description [Portable number generator based on ran2 from "Numerical
2678  Recipes in C." It is a long period (> 2 * 10^18) random number generator
2679  of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
2680  distributed between 0 and 2147483561 (inclusive of the endpoint values).
2681  The random generator can be explicitly initialized by calling
2682  Cudd_Srandom. If no explicit initialization is performed, then the
2683  seed 1 is assumed.]
2684
2685  SideEffects [None]
2686
2687  SeeAlso     [Cudd_Srandom]
2688
2689******************************************************************************/
2690long
2691Cudd_Random(void)
2692{
2693    int i;      /* index in the shuffle table */
2694    long int w; /* work variable */
2695
2696    /* cuddRand == 0 if the geneartor has not been initialized yet. */
2697    if (cuddRand == 0) Cudd_Srandom(1);
2698
2699    /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding
2700    ** overflows by Schrage's method.
2701    */
2702    w          = cuddRand / LEQQ1;
2703    cuddRand   = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
2704    cuddRand  += (cuddRand < 0) * MODULUS1;
2705
2706    /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding
2707    ** overflows by Schrage's method.
2708    */
2709    w          = cuddRand2 / LEQQ2;
2710    cuddRand2  = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
2711    cuddRand2 += (cuddRand2 < 0) * MODULUS2;
2712
2713    /* cuddRand is shuffled with the Bays-Durham algorithm.
2714    ** shuffleSelect and cuddRand2 are combined to generate the output.
2715    */
2716
2717    /* Pick one element from the shuffle table; "i" will be in the range
2718    ** from 0 to STAB_SIZE-1.
2719    */
2720    i = (int) (shuffleSelect / STAB_DIV);
2721    /* Mix the element of the shuffle table with the current iterate of
2722    ** the second sub-generator, and replace the chosen element of the
2723    ** shuffle table with the current iterate of the first sub-generator.
2724    */
2725    shuffleSelect   = shuffleTable[i] - cuddRand2;
2726    shuffleTable[i] = cuddRand;
2727    shuffleSelect  += (shuffleSelect < 1) * (MODULUS1 - 1);
2728    /* Since shuffleSelect != 0, and we want to be able to return 0,
2729    ** here we subtract 1 before returning.
2730    */
2731    return(shuffleSelect - 1);
2732
2733} /* end of Cudd_Random */
2734
2735
2736/**Function********************************************************************
2737
2738  Synopsis    [Initializer for the portable random number generator.]
2739
2740  Description [Initializer for the portable number generator based on
2741  ran2 in "Numerical Recipes in C." The input is the seed for the
2742  generator. If it is negative, its absolute value is taken as seed.
2743  If it is 0, then 1 is taken as seed. The initialized sets up the two
2744  recurrences used to generate a long-period stream, and sets up the
2745  shuffle table.]
2746
2747  SideEffects [None]
2748
2749  SeeAlso     [Cudd_Random]
2750
2751******************************************************************************/
2752void
2753Cudd_Srandom(
2754  long  seed)
2755{
2756    int i;
2757
2758    if (seed < 0)       cuddRand = -seed;
2759    else if (seed == 0) cuddRand = 1;
2760    else                cuddRand = seed;
2761    cuddRand2 = cuddRand;
2762    /* Load the shuffle table (after 11 warm-ups). */
2763    for (i = 0; i < STAB_SIZE + 11; i++) {
2764        long int w;
2765        w = cuddRand / LEQQ1;
2766        cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
2767        cuddRand += (cuddRand < 0) * MODULUS1;
2768        shuffleTable[i % STAB_SIZE] = cuddRand;
2769    }
2770    shuffleSelect = shuffleTable[1 % STAB_SIZE];
2771
2772} /* end of Cudd_Srandom */
2773
2774
2775/**Function********************************************************************
2776
2777  Synopsis    [Computes the density of a BDD or ADD.]
2778
2779  Description [Computes the density of a BDD or ADD. The density is
2780  the ratio of the number of minterms to the number of nodes. If 0 is
2781  passed as number of variables, the number of variables existing in
2782  the manager is used. Returns the density if successful; (double)
2783  CUDD_OUT_OF_MEM otherwise.]
2784
2785  SideEffects [None]
2786
2787  SeeAlso     [Cudd_CountMinterm Cudd_DagSize]
2788
2789******************************************************************************/
2790double
2791Cudd_Density(
2792  DdManager * dd /* manager */,
2793  DdNode * f /* function whose density is sought */,
2794  int  nvars /* size of the support of f */)
2795{
2796    double minterms;
2797    int nodes;
2798    double density;
2799
2800    if (nvars == 0) nvars = dd->size;
2801    minterms = Cudd_CountMinterm(dd,f,nvars);
2802    if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms);
2803    nodes = Cudd_DagSize(f);
2804    density = minterms / (double) nodes;
2805    return(density);
2806
2807} /* end of Cudd_Density */
2808
2809
2810/**Function********************************************************************
2811
2812  Synopsis    [Warns that a memory allocation failed.]
2813
2814  Description [Warns that a memory allocation failed.
2815  This function can be used as replacement of MMout_of_memory to prevent
2816  the safe_mem functions of the util package from exiting when malloc
2817  returns NULL. One possible use is in case of discretionary allocations;
2818  for instance, the allocation of memory to enlarge the computed table.]
2819
2820  SideEffects [None]
2821
2822  SeeAlso     []
2823
2824******************************************************************************/
2825void
2826Cudd_OutOfMem(
2827  long size /* size of the allocation that failed */)
2828{
2829    (void) fflush(stdout);
2830    (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
2831    return;
2832
2833} /* end of Cudd_OutOfMem */
2834
2835
2836/*---------------------------------------------------------------------------*/
2837/* Definition of internal functions                                          */
2838/*---------------------------------------------------------------------------*/
2839
2840
2841/**Function********************************************************************
2842
2843  Synopsis    [Prints a DD to the standard output. One line per node is
2844  printed.]
2845
2846  Description [Prints a DD to the standard output. One line per node is
2847  printed. Returns 1 if successful; 0 otherwise.]
2848
2849  SideEffects [None]
2850
2851  SeeAlso     [Cudd_PrintDebug]
2852
2853******************************************************************************/
2854int
2855cuddP(
2856  DdManager * dd,
2857  DdNode * f)
2858{
2859    int retval;
2860    st_table *table = st_init_table(st_ptrcmp,st_ptrhash);
2861
2862    if (table == NULL) return(0);
2863
2864    retval = dp2(dd,f,table);
2865    st_free_table(table);
2866    (void) fputc('\n',dd->out);
2867    return(retval);
2868
2869} /* end of cuddP */
2870
2871
2872/**Function********************************************************************
2873
2874  Synopsis [Frees the memory used to store the minterm counts recorded
2875  in the visited table.]
2876
2877  Description [Frees the memory used to store the minterm counts
2878  recorded in the visited table. Returns ST_CONTINUE.]
2879
2880  SideEffects [None]
2881
2882******************************************************************************/
2883enum st_retval
2884cuddStCountfree(
2885  char * key,
2886  char * value,
2887  char * arg)
2888{
2889    double      *d;
2890
2891    d = (double *)value;
2892    FREE(d);
2893    return(ST_CONTINUE);
2894
2895} /* end of cuddStCountfree */
2896
2897
2898/**Function********************************************************************
2899
2900  Synopsis    [Recursively collects all the nodes of a DD in a symbol
2901  table.]
2902
2903  Description [Traverses the DD f and collects all its nodes in a
2904  symbol table.  f is assumed to be a regular pointer and
2905  cuddCollectNodes guarantees this assumption in the recursive calls.
2906  Returns 1 in case of success; 0 otherwise.]
2907
2908  SideEffects [None]
2909
2910  SeeAlso     []
2911
2912******************************************************************************/
2913int
2914cuddCollectNodes(
2915  DdNode * f,
2916  st_table * visited)
2917{
2918    DdNode      *T, *E;
2919    int         retval;
2920
2921#ifdef DD_DEBUG
2922    assert(!Cudd_IsComplement(f));
2923#endif
2924
2925    /* If already visited, nothing to do. */
2926    if (st_is_member(visited, (char *) f) == 1)
2927        return(1);
2928
2929    /* Check for abnormal condition that should never happen. */
2930    if (f == NULL)
2931        return(0);
2932
2933    /* Mark node as visited. */
2934    if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
2935        return(0);
2936
2937    /* Check terminal case. */
2938    if (cuddIsConstant(f))
2939        return(1);
2940
2941    /* Recursive calls. */
2942    T = cuddT(f);
2943    retval = cuddCollectNodes(T,visited);
2944    if (retval != 1) return(retval);
2945    E = Cudd_Regular(cuddE(f));
2946    retval = cuddCollectNodes(E,visited);
2947    return(retval);
2948
2949} /* end of cuddCollectNodes */
2950
2951
2952/**Function********************************************************************
2953
2954  Synopsis    [Recursively collects all the nodes of a DD in an array.]
2955
2956  Description [Traverses the DD f and collects all its nodes in an array.
2957  The caller should free the array returned by cuddNodeArray.
2958  Returns a pointer to the array of nodes in case of success; NULL
2959  otherwise.  The nodes are collected in reverse topological order, so
2960  that a node is always preceded in the array by all its descendants.]
2961
2962  SideEffects [The number of nodes is returned as a side effect.]
2963
2964  SeeAlso     [Cudd_FirstNode]
2965
2966******************************************************************************/
2967DdNodePtr *
2968cuddNodeArray(
2969  DdNode *f,
2970  int *n)
2971{
2972    DdNodePtr *table;
2973    int size, retval;
2974
2975    size = ddDagInt(Cudd_Regular(f));
2976    table = ALLOC(DdNodePtr, size);
2977    if (table == NULL) {
2978        ddClearFlag(Cudd_Regular(f));
2979        return(NULL);
2980    }
2981
2982    retval = cuddNodeArrayRecur(f, table, 0);
2983    assert(retval == size);
2984
2985    *n = size;
2986    return(table);
2987 
2988} /* cuddNodeArray */
2989
2990
2991/*---------------------------------------------------------------------------*/
2992/* Definition of static functions                                            */
2993/*---------------------------------------------------------------------------*/
2994
2995
2996/**Function********************************************************************
2997
2998  Synopsis    [Performs the recursive step of cuddP.]
2999
3000  Description [Performs the recursive step of cuddP. Returns 1 in case
3001  of success; 0 otherwise.]
3002
3003  SideEffects [None]
3004
3005******************************************************************************/
3006static int
3007dp2(
3008  DdManager *dd,
3009  DdNode * f,
3010  st_table * t)
3011{
3012    DdNode *g, *n, *N;
3013    int T,E;
3014   
3015    if (f == NULL) {
3016        return(0);
3017    }
3018    g = Cudd_Regular(f);
3019    if (cuddIsConstant(g)) {
3020#if SIZEOF_VOID_P == 8
3021        (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
3022                (unsigned long) g / (unsigned long) sizeof(DdNode),cuddV(g));
3023#else
3024        (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
3025                (unsigned) g / (unsigned) sizeof(DdNode),cuddV(g));
3026#endif
3027        return(1);
3028    }
3029    if (st_is_member(t,(char *) g) == 1) {
3030        return(1);
3031    }
3032    if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM)
3033        return(0);
3034#ifdef DD_STATS
3035#if SIZEOF_VOID_P == 8
3036    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
3037                (unsigned long) g / (unsigned long) sizeof(DdNode), g->index, g->ref);
3038#else
3039    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
3040                (unsigned) g / (unsigned) sizeof(DdNode),g->index,g->ref);
3041#endif
3042#else
3043#if SIZEOF_VOID_P == 8
3044    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\t", bang(f),
3045                (unsigned long) g / (unsigned long) sizeof(DdNode),g->index);
3046#else
3047    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\t", bang(f),
3048                (unsigned) g / (unsigned) sizeof(DdNode),g->index);
3049#endif
3050#endif
3051    n = cuddT(g);
3052    if (cuddIsConstant(n)) {
3053        (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
3054        T = 1;
3055    } else {
3056#if SIZEOF_VOID_P == 8
3057        (void) fprintf(dd->out,"T = 0x%lx\t",(unsigned long) n / (unsigned long) sizeof(DdNode));
3058#else
3059        (void) fprintf(dd->out,"T = 0x%x\t",(unsigned) n / (unsigned) sizeof(DdNode));
3060#endif
3061        T = 0;
3062    }
3063
3064    n = cuddE(g);
3065    N = Cudd_Regular(n);
3066    if (cuddIsConstant(N)) {
3067        (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
3068        E = 1;
3069    } else {
3070#if SIZEOF_VOID_P == 8
3071        (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (unsigned long) N/(unsigned long) sizeof(DdNode));
3072#else
3073        (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (unsigned) N/(unsigned) sizeof(DdNode));
3074#endif
3075        E = 0;
3076    }
3077    if (E == 0) {
3078        if (dp2(dd,N,t) == 0)
3079            return(0);
3080    }
3081    if (T == 0) {
3082        if (dp2(dd,cuddT(g),t) == 0)
3083            return(0);
3084    }
3085    return(1);
3086
3087} /* end of dp2 */
3088
3089
3090/**Function********************************************************************
3091
3092  Synopsis    [Performs the recursive step of Cudd_PrintMinterm.]
3093
3094  Description []
3095
3096  SideEffects [None]
3097
3098******************************************************************************/
3099static void
3100ddPrintMintermAux(
3101  DdManager * dd /* manager */,
3102  DdNode * node /* current node */,
3103  int * list /* current recursion path */)
3104{
3105    DdNode      *N,*Nv,*Nnv;
3106    int         i,v,index;
3107
3108    N = Cudd_Regular(node);
3109
3110    if (cuddIsConstant(N)) {
3111        /* Terminal case: Print one cube based on the current recursion
3112        ** path, unless we have reached the background value (ADDs) or
3113        ** the logical zero (BDDs).
3114        */
3115        if (node != background && node != zero) {
3116            for (i = 0; i < dd->size; i++) {
3117                v = list[i];
3118                if (v == 0) (void) fprintf(dd->out,"0");
3119                else if (v == 1) (void) fprintf(dd->out,"1");
3120                else (void) fprintf(dd->out,"-");
3121            }
3122            (void) fprintf(dd->out," % g\n", cuddV(node));
3123        }
3124    } else {
3125        Nv  = cuddT(N);
3126        Nnv = cuddE(N);
3127        if (Cudd_IsComplement(node)) {
3128            Nv  = Cudd_Not(Nv);
3129            Nnv = Cudd_Not(Nnv);
3130        }
3131        index = N->index;
3132        list[index] = 0;
3133        ddPrintMintermAux(dd,Nnv,list); 
3134        list[index] = 1;
3135        ddPrintMintermAux(dd,Nv,list);
3136        list[index] = 2;
3137    }
3138    return;
3139
3140} /* end of ddPrintMintermAux */
3141
3142
3143/**Function********************************************************************
3144
3145  Synopsis    [Performs the recursive step of Cudd_DagSize.]
3146
3147  Description [Performs the recursive step of Cudd_DagSize. Returns the
3148  number of nodes in the graph rooted at n.]
3149
3150  SideEffects [None]
3151
3152******************************************************************************/
3153static int
3154ddDagInt(
3155  DdNode * n)
3156{
3157    int tval, eval;
3158
3159    if (Cudd_IsComplement(n->next)) {
3160        return(0);
3161    }
3162    n->next = Cudd_Not(n->next);
3163    if (cuddIsConstant(n)) {
3164        return(1);
3165    }
3166    tval = ddDagInt(cuddT(n));
3167    eval = ddDagInt(Cudd_Regular(cuddE(n)));
3168    return(1 + tval + eval);
3169
3170} /* end of ddDagInt */
3171
3172
3173/**Function********************************************************************
3174
3175  Synopsis    [Performs the recursive step of cuddNodeArray.]
3176
3177  Description [Performs the recursive step of cuddNodeArray.  Returns
3178  an the number of nodes in the DD.  Clear the least significant bit
3179  of the next field that was used as visited flag by
3180  cuddNodeArrayRecur when counting the nodes.  node is supposed to be
3181  regular; the invariant is maintained by this procedure.]
3182
3183  SideEffects [None]
3184
3185  SeeAlso     []
3186
3187******************************************************************************/
3188static int
3189cuddNodeArrayRecur(
3190  DdNode *f,
3191  DdNodePtr *table,
3192  int index)
3193{
3194    int tindex, eindex;
3195
3196    if (!Cudd_IsComplement(f->next)) {
3197        return(index);
3198    }
3199    /* Clear visited flag. */
3200    f->next = Cudd_Regular(f->next);
3201    if (cuddIsConstant(f)) {
3202        table[index] = f;
3203        return(index + 1);
3204    }
3205    tindex = cuddNodeArrayRecur(cuddT(f), table, index);
3206    eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
3207    table[eindex] = f;
3208    return(eindex + 1);
3209
3210} /* end of cuddNodeArrayRecur */
3211
3212
3213/**Function********************************************************************
3214
3215  Synopsis    [Performs the recursive step of Cudd_CofactorEstimate.]
3216
3217  Description [Performs the recursive step of Cudd_CofactorEstimate.
3218  Returns an estimate of the number of nodes in the DD of a
3219  cofactor of node. Uses the least significant bit of the next field as
3220  visited flag. node is supposed to be regular; the invariant is maintained
3221  by this procedure.]
3222
3223  SideEffects [None]
3224
3225  SeeAlso     []
3226
3227******************************************************************************/
3228static int
3229cuddEstimateCofactor(
3230  DdManager *dd,
3231  st_table *table,
3232  DdNode * node,
3233  int i,
3234  int phase,
3235  DdNode ** ptr)
3236{
3237    int tval, eval, val;
3238    DdNode *ptrT, *ptrE;
3239
3240    if (Cudd_IsComplement(node->next)) {
3241        if (!st_lookup(table,(char *)node,(char **)ptr)) {
3242            st_add_direct(table,(char *)node,(char *)node);
3243            *ptr = node;
3244        }
3245        return(0);
3246    }
3247    node->next = Cudd_Not(node->next);
3248    if (cuddIsConstant(node)) {
3249        *ptr = node;
3250        if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM)
3251            return(CUDD_OUT_OF_MEM);
3252        return(1);
3253    }
3254    if ((int) node->index == i) {
3255        if (phase == 1) {
3256            *ptr = cuddT(node);
3257            val = ddDagInt(cuddT(node));
3258        } else {
3259            *ptr = cuddE(node);
3260            val = ddDagInt(Cudd_Regular(cuddE(node)));
3261        }
3262        if (node->ref > 1) {
3263            if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3264                ST_OUT_OF_MEM)
3265                return(CUDD_OUT_OF_MEM);
3266        }
3267        return(val);
3268    }
3269    if (dd->perm[node->index] > dd->perm[i]) {
3270        *ptr = node;
3271        tval = ddDagInt(cuddT(node));
3272        eval = ddDagInt(Cudd_Regular(cuddE(node)));
3273        if (node->ref > 1) {
3274            if (st_add_direct(table,(char *)node,(char *)node) ==
3275                ST_OUT_OF_MEM)
3276                return(CUDD_OUT_OF_MEM);
3277        }
3278        val = 1 + tval + eval;
3279        return(val);
3280    }
3281    tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
3282    eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
3283                                phase,&ptrE);
3284    ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
3285    if (ptrT == ptrE) {         /* recombination */
3286        *ptr = ptrT;
3287        val = tval;
3288        if (node->ref > 1) {
3289            if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3290                    ST_OUT_OF_MEM)
3291                return(CUDD_OUT_OF_MEM);
3292        }
3293    } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
3294               (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
3295        if (Cudd_IsComplement((*ptr)->next)) {
3296            val = 0;
3297        } else {
3298            val = 1 + tval + eval;
3299        }
3300        if (node->ref > 1) {
3301            if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3302                    ST_OUT_OF_MEM)
3303                return(CUDD_OUT_OF_MEM);
3304        }
3305    } else {
3306        *ptr = node;
3307        val = 1 + tval + eval;
3308    }
3309    return(val);
3310
3311} /* end of cuddEstimateCofactor */
3312
3313
3314/**Function********************************************************************
3315
3316  Synopsis    [Checks the unique table for the existence of an internal node.]
3317
3318  Description [Checks the unique table for the existence of an internal
3319  node. Returns a pointer to the node if it is in the table; NULL otherwise.]
3320
3321  SideEffects [None]
3322
3323  SeeAlso     [cuddUniqueInter]
3324
3325******************************************************************************/
3326static DdNode *
3327cuddUniqueLookup(
3328  DdManager * unique,
3329  int  index,
3330  DdNode * T,
3331  DdNode * E)
3332{
3333    int posn;
3334    unsigned int level;
3335    DdNodePtr *nodelist;
3336    DdNode *looking;
3337    DdSubtable *subtable;
3338
3339    if (index >= unique->size) {
3340        return(NULL);
3341    }
3342
3343    level = unique->perm[index];
3344    subtable = &(unique->subtables[level]);
3345
3346#ifdef DD_DEBUG
3347    assert(level < (unsigned) cuddI(unique,T->index));
3348    assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
3349#endif
3350
3351    posn = ddHash(T, E, subtable->shift);
3352    nodelist = subtable->nodelist;
3353    looking = nodelist[posn];
3354
3355    while (T < cuddT(looking)) {
3356        looking = Cudd_Regular(looking->next);
3357    }
3358    while (T == cuddT(looking) && E < cuddE(looking)) {
3359        looking = Cudd_Regular(looking->next);
3360    }
3361    if (cuddT(looking) == T && cuddE(looking) == E) {
3362        return(looking);
3363    }
3364
3365    return(NULL);
3366
3367} /* end of cuddUniqueLookup */
3368
3369
3370/**Function********************************************************************
3371
3372  Synopsis    [Performs the recursive step of Cudd_CofactorEstimateSimple.]
3373
3374  Description [Performs the recursive step of Cudd_CofactorEstimateSimple.
3375  Returns an estimate of the number of nodes in the DD of the positive
3376  cofactor of node. Uses the least significant bit of the next field as
3377  visited flag. node is supposed to be regular; the invariant is maintained
3378  by this procedure.]
3379
3380  SideEffects [None]
3381
3382  SeeAlso     []
3383
3384******************************************************************************/
3385static int
3386cuddEstimateCofactorSimple(
3387  DdNode * node,
3388  int i)
3389{
3390    int tval, eval;
3391
3392    if (Cudd_IsComplement(node->next)) {
3393        return(0);
3394    }
3395    node->next = Cudd_Not(node->next);
3396    if (cuddIsConstant(node)) {
3397        return(1);
3398    }
3399    tval = cuddEstimateCofactorSimple(cuddT(node),i);
3400    if ((int) node->index == i) return(tval);
3401    eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i);
3402    return(1 + tval + eval);
3403
3404} /* end of cuddEstimateCofactorSimple */
3405
3406
3407/**Function********************************************************************
3408
3409  Synopsis    [Performs the recursive step of Cudd_CountMinterm.]
3410
3411  Description [Performs the recursive step of Cudd_CountMinterm.
3412  It is based on the following identity. Let |f| be the
3413  number of minterms of f. Then:
3414  <xmp>
3415    |f| = (|f0|+|f1|)/2
3416  </xmp>
3417  where f0 and f1 are the two cofactors of f.  Does not use the
3418  identity |f'| = max - |f|, to minimize loss of accuracy due to
3419  roundoff.  Returns the number of minterms of the function rooted at
3420  node.]
3421
3422  SideEffects [None]
3423
3424******************************************************************************/
3425static double
3426ddCountMintermAux(
3427  DdNode * node,
3428  double  max,
3429  DdHashTable * table)
3430{
3431    DdNode      *N, *Nt, *Ne;
3432    double      min, minT, minE;
3433    DdNode      *res;
3434
3435    N = Cudd_Regular(node);
3436
3437    if (cuddIsConstant(N)) {
3438        if (node == background || node == zero) {
3439            return(0.0);
3440        } else {
3441            return(max);
3442        }
3443    }
3444    if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
3445        min = cuddV(res);
3446        if (res->ref == 0) {
3447            table->manager->dead++;
3448            table->manager->constants.dead++;
3449        }
3450        return(min);
3451    }
3452
3453    Nt = cuddT(N); Ne = cuddE(N);
3454    if (Cudd_IsComplement(node)) {
3455        Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
3456    }
3457
3458    minT = ddCountMintermAux(Nt,max,table);
3459    if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3460    minT *= 0.5;
3461    minE = ddCountMintermAux(Ne,max,table);
3462    if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3463    minE *= 0.5;
3464    min = minT + minE;
3465
3466    if (N->ref != 1) {
3467        ptrint fanout = (ptrint) N->ref;
3468        cuddSatDec(fanout);
3469        res = cuddUniqueConst(table->manager,min);
3470        if (!cuddHashTableInsert1(table,node,res,fanout)) {
3471            cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
3472            return((double)CUDD_OUT_OF_MEM);
3473        }
3474    }
3475
3476    return(min);
3477
3478} /* end of ddCountMintermAux */
3479
3480
3481/**Function********************************************************************
3482
3483  Synopsis    [Performs the recursive step of Cudd_CountPath.]
3484
3485  Description [Performs the recursive step of Cudd_CountPath.
3486  It is based on the following identity. Let |f| be the
3487  number of paths of f. Then:
3488  <xmp>
3489    |f| = |f0|+|f1|
3490  </xmp>
3491  where f0 and f1 are the two cofactors of f.  Uses the
3492  identity |f'| = |f|, to improve the utilization of the (local) cache.
3493  Returns the number of paths of the function rooted at node.]
3494
3495  SideEffects [None]
3496
3497******************************************************************************/
3498static double
3499ddCountPathAux(
3500  DdNode * node,
3501  st_table * table)
3502{
3503
3504    DdNode      *Nv, *Nnv;
3505    double      paths, *ppaths, paths1, paths2;
3506    double      *dummy;
3507
3508
3509    if (cuddIsConstant(node)) {
3510        return(1.0);
3511    }
3512    if (st_lookup(table, node, &dummy)) {
3513        paths = *dummy;
3514        return(paths);
3515    }
3516
3517    Nv = cuddT(node); Nnv = cuddE(node);
3518
3519    paths1 = ddCountPathAux(Nv,table);
3520    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3521    paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
3522    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3523    paths = paths1 + paths2;
3524   
3525    ppaths = ALLOC(double,1);
3526    if (ppaths == NULL) {
3527        return((double)CUDD_OUT_OF_MEM);
3528    }
3529
3530    *ppaths = paths;
3531
3532    if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) {
3533        FREE(ppaths);
3534        return((double)CUDD_OUT_OF_MEM);
3535    }
3536    return(paths);
3537
3538} /* end of ddCountPathAux */
3539
3540
3541/**Function********************************************************************
3542
3543  Synopsis    [Performs the recursive step of Cudd_EpdCountMinterm.]
3544
3545  Description [Performs the recursive step of Cudd_EpdCountMinterm.
3546  It is based on the following identity. Let |f| be the
3547  number of minterms of f. Then:
3548  <xmp>
3549    |f| = (|f0|+|f1|)/2
3550  </xmp>
3551  where f0 and f1 are the two cofactors of f.  Does not use the
3552  identity |f'| = max - |f|, to minimize loss of accuracy due to
3553  roundoff.  Returns the number of minterms of the function rooted at
3554  node.]
3555
3556  SideEffects [None]
3557
3558******************************************************************************/
3559static int
3560ddEpdCountMintermAux(
3561  DdNode * node,
3562  EpDouble * max,
3563  EpDouble * epd,
3564  st_table * table)
3565{
3566    DdNode      *Nt, *Ne;
3567    EpDouble    *min, minT, minE;
3568    EpDouble    *res;
3569    int         status;
3570
3571    /* node is assumed to be regular */
3572    if (cuddIsConstant(node)) {
3573        if (node == background || node == zero) {
3574            EpdMakeZero(epd, 0);
3575        } else {
3576            EpdCopy(max, epd);
3577        }
3578        return(0);
3579    }
3580    if (node->ref != 1 && st_lookup(table, node, &res)) {
3581        EpdCopy(res, epd);
3582        return(0);
3583    }
3584
3585    Nt = cuddT(node); Ne = cuddE(node);
3586
3587    status = ddEpdCountMintermAux(Nt,max,&minT,table);
3588    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
3589    EpdMultiply(&minT, (double)0.5);
3590    status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
3591    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
3592    if (Cudd_IsComplement(Ne)) {
3593        EpdSubtract3(max, &minE, epd);
3594        EpdCopy(epd, &minE);
3595    }
3596    EpdMultiply(&minE, (double)0.5);
3597    EpdAdd3(&minT, &minE, epd);
3598
3599    if (node->ref > 1) {
3600        min = EpdAlloc();
3601        if (!min)
3602            return(CUDD_OUT_OF_MEM);
3603        EpdCopy(epd, min);
3604        if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) {
3605            EpdFree(min);
3606            return(CUDD_OUT_OF_MEM);
3607        }
3608    }
3609
3610    return(0);
3611
3612} /* end of ddEpdCountMintermAux */
3613
3614
3615/**Function********************************************************************
3616
3617  Synopsis    [Performs the recursive step of Cudd_CountPathsToNonZero.]
3618
3619  Description [Performs the recursive step of Cudd_CountPathsToNonZero.
3620  It is based on the following identity. Let |f| be the
3621  number of paths of f. Then:
3622  <xmp>
3623    |f| = |f0|+|f1|
3624  </xmp>
3625  where f0 and f1 are the two cofactors of f.  Returns the number of
3626  paths of the function rooted at node.]
3627
3628  SideEffects [None]
3629
3630******************************************************************************/
3631static double
3632ddCountPathsToNonZero(
3633  DdNode * N,
3634  st_table * table)
3635{
3636
3637    DdNode      *node, *Nt, *Ne;
3638    double      paths, *ppaths, paths1, paths2;
3639    double      *dummy;
3640
3641    node = Cudd_Regular(N);
3642    if (cuddIsConstant(node)) {
3643        return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
3644    }
3645    if (st_lookup(table, N, &dummy)) {
3646        paths = *dummy;
3647        return(paths);
3648    }
3649
3650    Nt = cuddT(node); Ne = cuddE(node);
3651    if (node != N) {
3652        Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
3653    }
3654
3655    paths1 = ddCountPathsToNonZero(Nt,table);
3656    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3657    paths2 = ddCountPathsToNonZero(Ne,table);
3658    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3659    paths = paths1 + paths2;
3660
3661    ppaths = ALLOC(double,1);
3662    if (ppaths == NULL) {
3663        return((double)CUDD_OUT_OF_MEM);
3664    }
3665
3666    *ppaths = paths;
3667
3668    if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) {
3669        FREE(ppaths);
3670        return((double)CUDD_OUT_OF_MEM);
3671    }
3672    return(paths);
3673
3674} /* end of ddCountPathsToNonZero */
3675
3676
3677/**Function********************************************************************
3678
3679  Synopsis    [Performs the recursive step of Cudd_Support.]
3680
3681  Description [Performs the recursive step of Cudd_Support. Performs a
3682  DFS from f. The support is accumulated in supp as a side effect. Uses
3683  the LSB of the then pointer as visited flag.]
3684
3685  SideEffects [None]
3686
3687  SeeAlso     [ddClearFlag]
3688
3689******************************************************************************/
3690static void
3691ddSupportStep(
3692  DdNode * f,
3693  int * support)
3694{
3695    if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
3696        return;
3697    }
3698
3699    support[f->index] = 1;
3700    ddSupportStep(cuddT(f),support);
3701    ddSupportStep(Cudd_Regular(cuddE(f)),support);
3702    /* Mark as visited. */
3703    f->next = Cudd_Not(f->next);
3704    return;
3705
3706} /* end of ddSupportStep */
3707
3708
3709/**Function********************************************************************
3710
3711  Synopsis    [Performs a DFS from f, clearing the LSB of the next
3712  pointers.]
3713
3714  Description []
3715
3716  SideEffects [None]
3717
3718  SeeAlso     [ddSupportStep ddDagInt]
3719
3720******************************************************************************/
3721static void
3722ddClearFlag(
3723  DdNode * f)
3724{
3725    if (!Cudd_IsComplement(f->next)) {
3726        return;
3727    }
3728    /* Clear visited flag. */
3729    f->next = Cudd_Regular(f->next);
3730    if (cuddIsConstant(f)) {
3731        return;
3732    }
3733    ddClearFlag(cuddT(f));
3734    ddClearFlag(Cudd_Regular(cuddE(f)));
3735    return;
3736
3737} /* end of ddClearFlag */
3738
3739
3740/**Function********************************************************************
3741
3742  Synopsis    [Performs the recursive step of Cudd_CountLeaves.]
3743
3744  Description [Performs the recursive step of Cudd_CountLeaves. Returns
3745  the number of leaves in the DD rooted at n.]
3746
3747  SideEffects [None]
3748
3749  SeeAlso     [Cudd_CountLeaves]
3750
3751******************************************************************************/
3752static int
3753ddLeavesInt(
3754  DdNode * n)
3755{
3756    int tval, eval;
3757
3758    if (Cudd_IsComplement(n->next)) {
3759        return(0);
3760    }
3761    n->next = Cudd_Not(n->next);
3762    if (cuddIsConstant(n)) {
3763        return(1);
3764    }
3765    tval = ddLeavesInt(cuddT(n));
3766    eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
3767    return(tval + eval);
3768
3769} /* end of ddLeavesInt */
3770
3771
3772/**Function********************************************************************
3773
3774  Synopsis    [Performs the recursive step of Cudd_bddPickArbitraryMinterms.]
3775
3776  Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms.
3777  Returns 1 if successful; 0 otherwise.]
3778
3779  SideEffects [none]
3780
3781  SeeAlso [Cudd_bddPickArbitraryMinterms]
3782
3783******************************************************************************/
3784static int
3785ddPickArbitraryMinterms(
3786  DdManager *dd,
3787  DdNode *node,
3788  int nvars,
3789  int nminterms,
3790  char **string)
3791{
3792    DdNode *N, *T, *E;
3793    DdNode *one, *bzero;
3794    int    i, t, result;
3795    double min1, min2;
3796
3797    if (string == NULL || node == NULL) return(0);
3798
3799    /* The constant 0 function has no on-set cubes. */
3800    one = DD_ONE(dd);
3801    bzero = Cudd_Not(one);
3802    if (nminterms == 0 || node == bzero) return(1);
3803    if (node == one) {
3804        return(1);
3805    }
3806
3807    N = Cudd_Regular(node);
3808    T = cuddT(N); E = cuddE(N);
3809    if (Cudd_IsComplement(node)) {
3810        T = Cudd_Not(T); E = Cudd_Not(E);
3811    }
3812
3813    min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
3814    if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
3815    min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
3816    if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
3817
3818    t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
3819    for (i = 0; i < t; i++)
3820        string[i][N->index] = '1';
3821    for (i = t; i < nminterms; i++)
3822        string[i][N->index] = '0';
3823
3824    result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
3825    if (result == 0)
3826        return(0);
3827    result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
3828    return(result);
3829
3830} /* end of ddPickArbitraryMinterms */
3831
3832
3833/**Function********************************************************************
3834
3835  Synopsis    [Finds a representative cube of a BDD.]
3836
3837  Description [Finds a representative cube of a BDD with the weight of
3838  each variable. From the top variable, if the weight is greater than or
3839  equal to 0.0, choose THEN branch unless the child is the constant 0.
3840  Otherwise, choose ELSE branch unless the child is the constant 0.]
3841
3842  SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube]
3843
3844******************************************************************************/
3845static int
3846ddPickRepresentativeCube(
3847  DdManager *dd,
3848  DdNode *node,
3849  int nvars,
3850  double *weight,
3851  char *string)
3852{
3853    DdNode *N, *T, *E;
3854    DdNode *one, *bzero;
3855
3856    if (string == NULL || node == NULL) return(0);
3857
3858    /* The constant 0 function has no on-set cubes. */
3859    one = DD_ONE(dd);
3860    bzero = Cudd_Not(one);
3861    if (node == bzero) return(0);
3862
3863    if (node == DD_ONE(dd)) return(1);
3864
3865    for (;;) {
3866        N = Cudd_Regular(node);
3867        if (N == one)
3868            break;
3869        T = cuddT(N);
3870        E = cuddE(N);
3871        if (Cudd_IsComplement(node)) {
3872            T = Cudd_Not(T);
3873            E = Cudd_Not(E);
3874        }
3875        if (weight[N->index] >= 0.0) {
3876            if (T == bzero) {
3877                node = E;
3878                string[N->index] = '0';
3879            } else {
3880                node = T;
3881                string[N->index] = '1';
3882            }
3883        } else {
3884            if (E == bzero) {
3885                node = T;
3886                string[N->index] = '1';
3887            } else {
3888                node = E;
3889                string[N->index] = '0';
3890            }
3891        }
3892    }
3893    return(1);
3894
3895} /* end of ddPickRepresentativeCube */
3896
3897
3898/**Function********************************************************************
3899
3900  Synopsis [Frees the memory used to store the minterm counts recorded
3901  in the visited table.]
3902
3903  Description [Frees the memory used to store the minterm counts
3904  recorded in the visited table. Returns ST_CONTINUE.]
3905
3906  SideEffects [None]
3907
3908******************************************************************************/
3909static enum st_retval
3910ddEpdFree(
3911  char * key,
3912  char * value,
3913  char * arg)
3914{
3915    EpDouble    *epd;
3916
3917    epd = (EpDouble *) value;
3918    EpdFree(epd);
3919    return(ST_CONTINUE);
3920
3921} /* end of ddEpdFree */
Note: See TracBrowser for help on using the repository browser.