abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddSubsetSP.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddSubsetSP.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Procedure to subset the given BDD choosing the shortest paths
8  (largest cubes) in the BDD.]
9 
10 
11  Description [External procedures included in this module:
12  <ul>
13  <li> Cudd_SubsetShortPaths()
14  <li> Cudd_SupersetShortPaths()
15  </ul>
16  Internal procedures included in this module:
17  <ul>
18  <li> cuddSubsetShortPaths()
19  </ul>
20  Static procedures included in this module:
21  <ul>
22  <li> BuildSubsetBdd()
23  <li> CreatePathTable()
24  <li> AssessPathLength()
25  <li> CreateTopDist()
26  <li> CreateBotDist()
27  <li> ResizeNodeDistPages()
28  <li> ResizeQueuePages()
29  <li> stPathTableDdFree()
30  </ul>
31  ]
32 
33  SeeAlso [cuddSubsetHB.c]
34 
35  Author [Kavita Ravi]
36 
37  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
38 
39  All rights reserved.
40 
41  Redistribution and use in source and binary forms, with or without
42  modification, are permitted provided that the following conditions
43  are met:
44 
45  Redistributions of source code must retain the above copyright
46  notice, this list of conditions and the following disclaimer.
47 
48  Redistributions in binary form must reproduce the above copyright
49  notice, this list of conditions and the following disclaimer in the
50  documentation and/or other materials provided with the distribution.
51 
52  Neither the name of the University of Colorado nor the names of its
53  contributors may be used to endorse or promote products derived from
54  this software without specific prior written permission.
55 
56  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
57  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
58  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
59  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
60  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
61  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
62  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
63  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
66  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
67  POSSIBILITY OF SUCH DAMAGE.]
68 
69 ******************************************************************************/
70 
71 #include "misc/util/util_hack.h"
72 #include "cuddInt.h"
73 
75 
76 
77 
78 /*---------------------------------------------------------------------------*/
79 /* Constant declarations */
80 /*---------------------------------------------------------------------------*/
81 
82 #define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */
83 #define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /* page sizesto store NodeDist_t type */
84 #define MAXSHORTINT ((DdHalfWord) ~0) /* constant defined to store
85  * maximum distance of a node
86  * from the root or the
87  * constant
88  */
89 #define INITIAL_PAGES 128 /* number of initial pages for the
90  * queue/NodeDist_t type */
91 
92 /*---------------------------------------------------------------------------*/
93 /* Stucture declarations */
94 /*---------------------------------------------------------------------------*/
95 
96 /* structure created to store subset results for each node and distances with
97  * odd and even parity of the node from the root and sink. Main data structure
98  * in this procedure.
99  */
100 struct NodeDist{
107 };
108 
109 /* assorted information needed by the BuildSubsetBdd procedure. */
110 struct AssortedInfo {
111  unsigned int maxpath;
116 };
117 
118 /*---------------------------------------------------------------------------*/
119 /* Type declarations */
120 /*---------------------------------------------------------------------------*/
121 
122 typedef struct NodeDist NodeDist_t;
123 
124 /*---------------------------------------------------------------------------*/
125 /* Variable declarations */
126 /*---------------------------------------------------------------------------*/
127 
128 #ifndef lint
129 static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $";
130 #endif
131 
132 #ifdef DD_DEBUG
133 static int numCalls;
134 static int hits;
135 static int thishit;
136 #endif
137 
138 
139 static int memOut; /* flag to indicate out of memory */
140 static DdNode *zero, *one; /* constant functions */
141 
142 static NodeDist_t **nodeDistPages; /* pointers to the pages */
143 static int nodeDistPageIndex; /* index to next element */
144 static int nodeDistPage; /* index to current page */
145 static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */
146 static int maxNodeDistPages; /* number of page pointers */
147 static NodeDist_t *currentNodeDistPage; /* current page */
148 
149 static DdNode ***queuePages; /* pointers to the pages */
150 static int queuePageIndex; /* index to next element */
151 static int queuePage; /* index to current page */
152 static int queuePageSize = DEFAULT_PAGE_SIZE; /* page size */
153 static int maxQueuePages; /* number of page pointers */
154 static DdNode **currentQueuePage; /* current page */
155 
156 
157 /*---------------------------------------------------------------------------*/
158 /* Macro declarations */
159 /*---------------------------------------------------------------------------*/
160 
161 #ifdef __cplusplus
162 extern "C" {
163 #endif
164 
165 /**AutomaticStart*************************************************************/
166 
167 /*---------------------------------------------------------------------------*/
168 /* Static function prototypes */
169 /*---------------------------------------------------------------------------*/
170 
171 static void ResizeNodeDistPages (void);
172 static void ResizeQueuePages (void);
173 static void CreateTopDist ( st__table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp);
174 static int CreateBotDist (DdNode *node, st__table *pathTable, unsigned int *pathLengthArray, FILE *fp);
175 static st__table * CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp);
176 static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp);
177 static DdNode * BuildSubsetBdd (DdManager *dd, st__table *pathTable, DdNode *node, struct AssortedInfo *info, st__table *subsetNodeTable);
178 static enum st__retval stPathTableDdFree (char *key, char *value, char *arg);
179 
180 /**AutomaticEnd***************************************************************/
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 /*---------------------------------------------------------------------------*/
187 /* Definition of Exported functions */
188 /*---------------------------------------------------------------------------*/
189 
190 
191 /**Function********************************************************************
192 
193  Synopsis [Extracts a dense subset from a BDD with the shortest paths
194  heuristic.]
195 
196  Description [Extracts a dense subset from a BDD. This procedure
197  tries to preserve the shortest paths of the input BDD, because they
198  give many minterms and contribute few nodes. This procedure may
199  increase the number of nodes in trying to create the subset or
200  reduce the number of nodes due to recombination as compared to the
201  original BDD. Hence the threshold may not be strictly adhered to. In
202  practice, recombination overshadows the increase in the number of
203  nodes and results in small BDDs as compared to the threshold. The
204  hardlimit specifies whether threshold needs to be strictly adhered
205  to. If it is set to 1, the procedure ensures that result is never
206  larger than the specified limit but may be considerably less than
207  the threshold. Returns a pointer to the BDD for the subset if
208  successful; NULL otherwise. The value for numVars should be as
209  close as possible to the size of the support of f for better
210  efficiency. However, it is safe to pass the value returned by
211  Cudd_ReadSize for numVars. If 0 is passed, then the value returned
212  by Cudd_ReadSize is used.]
213 
214  SideEffects [None]
215 
216  SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
217 
218 ******************************************************************************/
219 DdNode *
221  DdManager * dd /* manager */,
222  DdNode * f /* function to be subset */,
223  int numVars /* number of variables in the support of f */,
224  int threshold /* maximum number of nodes in the subset */,
225  int hardlimit /* flag: 1 if threshold is a hard limit */)
226 {
227  DdNode *subset;
228 
229  memOut = 0;
230  do {
231  dd->reordered = 0;
232  subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit);
233  } while((dd->reordered ==1) && (!memOut));
234 
235  return(subset);
236 
237 } /* end of Cudd_SubsetShortPaths */
238 
239 
240 /**Function********************************************************************
241 
242  Synopsis [Extracts a dense superset from a BDD with the shortest paths
243  heuristic.]
244 
245  Description [Extracts a dense superset from a BDD. The procedure is
246  identical to the subset procedure except for the fact that it
247  receives the complement of the given function. Extracting the subset
248  of the complement function is equivalent to extracting the superset
249  of the function. This procedure tries to preserve the shortest
250  paths of the complement BDD, because they give many minterms and
251  contribute few nodes. This procedure may increase the number of
252  nodes in trying to create the superset or reduce the number of nodes
253  due to recombination as compared to the original BDD. Hence the
254  threshold may not be strictly adhered to. In practice, recombination
255  overshadows the increase in the number of nodes and results in small
256  BDDs as compared to the threshold. The hardlimit specifies whether
257  threshold needs to be strictly adhered to. If it is set to 1, the
258  procedure ensures that result is never larger than the specified
259  limit but may be considerably less than the threshold. Returns a
260  pointer to the BDD for the superset if successful; NULL
261  otherwise. The value for numVars should be as close as possible to
262  the size of the support of f for better efficiency. However, it is
263  safe to pass the value returned by Cudd_ReadSize for numVar. If 0
264  is passed, then the value returned by Cudd_ReadSize is used.]
265 
266  SideEffects [None]
267 
268  SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
269 
270 ******************************************************************************/
271 DdNode *
273  DdManager * dd /* manager */,
274  DdNode * f /* function to be superset */,
275  int numVars /* number of variables in the support of f */,
276  int threshold /* maximum number of nodes in the subset */,
277  int hardlimit /* flag: 1 if threshold is a hard limit */)
278 {
279  DdNode *subset, *g;
280 
281  g = Cudd_Not(f);
282  memOut = 0;
283  do {
284  dd->reordered = 0;
285  subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit);
286  } while((dd->reordered ==1) && (!memOut));
287 
288  return(Cudd_NotCond(subset, (subset != NULL)));
289 
290 } /* end of Cudd_SupersetShortPaths */
291 
292 
293 /*---------------------------------------------------------------------------*/
294 /* Definition of internal functions */
295 /*---------------------------------------------------------------------------*/
296 
297 
298 /**Function********************************************************************
299 
300  Synopsis [The outermost procedure to return a subset of the given BDD
301  with the shortest path lengths.]
302 
303  Description [The outermost procedure to return a subset of the given
304  BDD with the largest cubes. The path lengths are calculated, the maximum
305  allowable path length is determined and the number of nodes of this
306  path length that can be used to build a subset. If the threshold is
307  larger than the size of the original BDD, the original BDD is
308  returned. ]
309 
310  SideEffects [None]
311 
312  SeeAlso [Cudd_SubsetShortPaths]
313 
314 ******************************************************************************/
315 DdNode *
317  DdManager * dd /* DD manager */,
318  DdNode * f /* function to be subset */,
319  int numVars /* total number of variables in consideration */,
320  int threshold /* maximum number of nodes allowed in the subset */,
321  int hardlimit /* flag determining whether thershold should be respected strictly */)
322 {
323  st__table *pathTable;
324  DdNode *N, *subset;
325 
326  unsigned int *pathLengthArray;
327  unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
328  int i;
329  NodeDist_t *nodeStat;
330  struct AssortedInfo *info;
331  st__table *subsetNodeTable;
332 
333  one = DD_ONE(dd);
334  zero = Cudd_Not(one);
335 
336  if (numVars == 0) {
337  /* set default value */
338  numVars = Cudd_ReadSize(dd);
339  }
340 
341  if (threshold > numVars) {
342  threshold = threshold - numVars;
343  }
344  if (f == NULL) {
345  fprintf(dd->err, "Cannot partition, nil object\n");
347  return(NULL);
348  }
349  if (Cudd_IsConstant(f))
350  return (f);
351 
352  pathLengthArray = ABC_ALLOC(unsigned int, numVars+1);
353  for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
354 
355 
356 #ifdef DD_DEBUG
357  numCalls = 0;
358 #endif
359 
360  pathTable = CreatePathTable(f, pathLengthArray, dd->err);
361 
362  if ((pathTable == NULL) || (memOut)) {
363  if (pathTable != NULL)
364  st__free_table(pathTable);
365  ABC_FREE(pathLengthArray);
366  return (NIL(DdNode));
367  }
368 
369  excess = ABC_ALLOC(unsigned int, 1);
370  *excess = 0;
371  maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
372  dd->err);
373 
374  if (maxpath != (unsigned) (numVars + 1)) {
375 
376  info = ABC_ALLOC(struct AssortedInfo, 1);
377  info->maxpath = maxpath;
378  info->findShortestPath = 0;
379  info->thresholdReached = *excess;
381  info->threshold = threshold;
382 
383 #ifdef DD_DEBUG
384  (void) fprintf(dd->out, "Path length array\n");
385  for (i = 0; i < (numVars+1); i++) {
386  if (pathLengthArray[i])
387  (void) fprintf(dd->out, "%d ",i);
388  }
389  (void) fprintf(dd->out, "\n");
390  for (i = 0; i < (numVars+1); i++) {
391  if (pathLengthArray[i])
392  (void) fprintf(dd->out, "%d ",pathLengthArray[i]);
393  }
394  (void) fprintf(dd->out, "\n");
395  (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n",
396  maxpath, info->thresholdReached);
397 #endif
398 
399  N = Cudd_Regular(f);
400  if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
401  fprintf(dd->err, "Something wrong, root node must be in table\n");
403  ABC_FREE(excess);
404  ABC_FREE(info);
405  return(NULL);
406  } else {
407  if ((nodeStat->oddTopDist != MAXSHORTINT) &&
408  (nodeStat->oddBotDist != MAXSHORTINT))
409  oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
410  else
411  oddLen = MAXSHORTINT;
412 
413  if ((nodeStat->evenTopDist != MAXSHORTINT) &&
414  (nodeStat->evenBotDist != MAXSHORTINT))
415  evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
416  else
417  evenLen = MAXSHORTINT;
418 
419  pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
420  if (pathLength > maxpath) {
421  (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength);
423  return(NULL);
424  }
425  }
426 
427 #ifdef DD_DEBUG
428  numCalls = 0;
429  hits = 0;
430  thishit = 0;
431 #endif
432  /* initialize a table to store computed nodes */
433  if (hardlimit) {
434  subsetNodeTable = st__init_table( st__ptrcmp, st__ptrhash);
435  } else {
436  subsetNodeTable = NIL( st__table);
437  }
438  subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
439  if (subset != NULL) {
440  cuddRef(subset);
441  }
442  /* record the number of times a computed result for a node is hit */
443 
444 #ifdef DD_DEBUG
445  (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
446  hits, thishit, numCalls);
447 #endif
448 
449  if (subsetNodeTable != NIL( st__table)) {
450  st__free_table(subsetNodeTable);
451  }
453  st__foreach(pathTable, stPathTableDdFree, (char *)dd);
454 
455  ABC_FREE(info);
456 
457  } else {/* if threshold larger than size of dd */
458  subset = f;
459  cuddRef(subset);
460  }
461  ABC_FREE(excess);
462  st__free_table(pathTable);
463  ABC_FREE(pathLengthArray);
464  for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
465  ABC_FREE(nodeDistPages);
466 
467 #ifdef DD_DEBUG
468  /* check containment of subset in f */
469  if (subset != NULL) {
470  DdNode *check;
471  check = Cudd_bddIteConstant(dd, subset, f, one);
472  if (check != one) {
473  (void) fprintf(dd->err, "Wrong partition\n");
475  return(NULL);
476  }
477  }
478 #endif
479 
480  if (subset != NULL) {
481  cuddDeref(subset);
482  return(subset);
483  } else {
484  return(NULL);
485  }
486 
487 } /* end of cuddSubsetShortPaths */
488 
489 
490 /*---------------------------------------------------------------------------*/
491 /* Definition of static functions */
492 /*---------------------------------------------------------------------------*/
493 
494 
495 /**Function********************************************************************
496 
497  Synopsis [Resize the number of pages allocated to store the distances
498  related to each node.]
499 
500  Description [Resize the number of pages allocated to store the distances
501  related to each node. The procedure moves the counter to the
502  next page when the end of the page is reached and allocates new
503  pages when necessary. ]
504 
505  SideEffects [Changes the size of pages, page, page index, maximum
506  number of pages freeing stuff in case of memory out. ]
507 
508  SeeAlso []
509 
510 ******************************************************************************/
511 static void
513 {
514  int i;
515  NodeDist_t **newNodeDistPages;
516 
517  /* move to next page */
518  nodeDistPage++;
519 
520  /* If the current page index is larger than the number of pages
521  * allocated, allocate a new page array. Page numbers are incremented by
522  * INITIAL_PAGES
523  */
525  newNodeDistPages = ABC_ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES);
526  if (newNodeDistPages == NULL) {
527  for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
528  ABC_FREE(nodeDistPages);
529  memOut = 1;
530  return;
531  } else {
532  for (i = 0; i < maxNodeDistPages; i++) {
533  newNodeDistPages[i] = nodeDistPages[i];
534  }
535  /* Increase total page count */
536  maxNodeDistPages += INITIAL_PAGES;
537  ABC_FREE(nodeDistPages);
538  nodeDistPages = newNodeDistPages;
539  }
540  }
541  /* Allocate a new page */
542  currentNodeDistPage = nodeDistPages[nodeDistPage] = ABC_ALLOC(NodeDist_t,
544  if (currentNodeDistPage == NULL) {
545  for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
546  ABC_FREE(nodeDistPages);
547  memOut = 1;
548  return;
549  }
550  /* reset page index */
551  nodeDistPageIndex = 0;
552  return;
553 
554 } /* end of ResizeNodeDistPages */
555 
556 
557 /**Function********************************************************************
558 
559  Synopsis [Resize the number of pages allocated to store nodes in the BFS
560  traversal of the Bdd .]
561 
562  Description [Resize the number of pages allocated to store nodes in the BFS
563  traversal of the Bdd. The procedure moves the counter to the
564  next page when the end of the page is reached and allocates new
565  pages when necessary.]
566 
567  SideEffects [Changes the size of pages, page, page index, maximum
568  number of pages freeing stuff in case of memory out. ]
569 
570  SeeAlso []
571 
572 ******************************************************************************/
573 static void
575 {
576  int i;
577  DdNode ***newQueuePages;
578 
579  queuePage++;
580  /* If the current page index is larger than the number of pages
581  * allocated, allocate a new page array. Page numbers are incremented by
582  * INITIAL_PAGES
583  */
584  if (queuePage == maxQueuePages) {
585  newQueuePages = ABC_ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES);
586  if (newQueuePages == NULL) {
587  for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]);
588  ABC_FREE(queuePages);
589  memOut = 1;
590  return;
591  } else {
592  for (i = 0; i < maxQueuePages; i++) {
593  newQueuePages[i] = queuePages[i];
594  }
595  /* Increase total page count */
596  maxQueuePages += INITIAL_PAGES;
597  ABC_FREE(queuePages);
598  queuePages = newQueuePages;
599  }
600  }
601  /* Allocate a new page */
602  currentQueuePage = queuePages[queuePage] = ABC_ALLOC(DdNode *,queuePageSize);
603  if (currentQueuePage == NULL) {
604  for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]);
605  ABC_FREE(queuePages);
606  memOut = 1;
607  return;
608  }
609  /* reset page index */
610  queuePageIndex = 0;
611  return;
612 
613 } /* end of ResizeQueuePages */
614 
615 
616 /**Function********************************************************************
617 
618  Synopsis [ Labels each node with its shortest distance from the root]
619 
620  Description [ Labels each node with its shortest distance from the root.
621  This is done in a BFS search of the BDD. The nodes are processed
622  in a queue implemented as pages(array) to reduce memory fragmentation.
623  An entry is created for each node visited. The distance from the root
624  to the node with the corresponding parity is updated. The procedure
625  is called recursively each recusion level handling nodes at a given
626  level from the root.]
627 
628 
629  SideEffects [Creates entries in the pathTable]
630 
631  SeeAlso [CreatePathTable CreateBotDist]
632 
633 ******************************************************************************/
634 static void
636  st__table * pathTable /* hast table to store path lengths */,
637  int parentPage /* the pointer to the page on which the first parent in the queue is to be found. */,
638  int parentQueueIndex /* pointer to the first parent on the page */,
639  int topLen /* current distance from the root */,
640  DdNode ** childPage /* pointer to the page on which the first child is to be added. */,
641  int childQueueIndex /* pointer to the first child */,
642  int numParents /* number of parents to process in this recursive call */,
643  FILE *fp /* where to write messages */)
644 {
645  NodeDist_t *nodeStat;
646  DdNode *N, *Nv, *Nnv, *node, *child, *regChild;
647  int i;
648  int processingDone, childrenCount;
649 
650 #ifdef DD_DEBUG
651  numCalls++;
652 
653  /* assume this procedure comes in with only the root node*/
654  /* set queue index to the next available entry for addition */
655  /* set queue page to page of addition */
656  if ((queuePages[parentPage] == childPage) && (parentQueueIndex ==
657  childQueueIndex)) {
658  fprintf(fp, "Should not happen that they are equal\n");
659  }
660  assert(queuePageIndex == childQueueIndex);
661  assert(currentQueuePage == childPage);
662 #endif
663  /* number children added to queue is initialized , needed for
664  * numParents in the next call
665  */
666  childrenCount = 0;
667  /* process all the nodes in this level */
668  while (numParents) {
669  numParents--;
670  if (parentQueueIndex == queuePageSize) {
671  parentPage++;
672  parentQueueIndex = 0;
673  }
674  /* a parent to process */
675  node = *(queuePages[parentPage] + parentQueueIndex);
676  parentQueueIndex++;
677  /* get its children */
678  N = Cudd_Regular(node);
679  Nv = Cudd_T(N);
680  Nnv = Cudd_E(N);
681 
682  Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
683  Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
684 
685  processingDone = 2;
686  while (processingDone) {
687  /* processing the THEN and the ELSE children, the THEN
688  * child first
689  */
690  if (processingDone == 2) {
691  child = Nv;
692  } else {
693  child = Nnv;
694  }
695 
696  regChild = Cudd_Regular(child);
697  /* dont process if the child is a constant */
698  if (!Cudd_IsConstant(child)) {
699  /* check is already visited, if not add a new entry in
700  * the path Table
701  */
702  if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStat)) {
703  /* if not in table, has never been visited */
704  /* create entry for table */
707  if (memOut) {
708  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
709  ABC_FREE(queuePages);
710  st__free_table(pathTable);
711  return;
712  }
713  /* New entry for child in path Table is created here */
714  nodeStat = currentNodeDistPage + nodeDistPageIndex;
715  nodeDistPageIndex++;
716 
717  /* Initialize fields of the node data */
718  nodeStat->oddTopDist = MAXSHORTINT;
719  nodeStat->evenTopDist = MAXSHORTINT;
720  nodeStat->evenBotDist = MAXSHORTINT;
721  nodeStat->oddBotDist = MAXSHORTINT;
722  nodeStat->regResult = NULL;
723  nodeStat->compResult = NULL;
724  /* update the table entry element, the distance keeps
725  * track of the parity of the path from the root
726  */
727  if (Cudd_IsComplement(child)) {
728  nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
729  } else {
730  nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
731  }
732 
733  /* insert entry element for child in the table */
734  if ( st__insert(pathTable, (char *)regChild,
735  (char *)nodeStat) == st__OUT_OF_MEM) {
736  memOut = 1;
737  for (i = 0; i <= nodeDistPage; i++)
738  ABC_FREE(nodeDistPages[i]);
739  ABC_FREE(nodeDistPages);
740  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
741  ABC_FREE(queuePages);
742  st__free_table(pathTable);
743  return;
744  }
745 
746  /* Create list element for this child to process its children.
747  * If this node has been processed already, then it appears
748  * in the path table and hence is never added to the list
749  * again.
750  */
751 
753  if (memOut) {
754  for (i = 0; i <= nodeDistPage; i++)
755  ABC_FREE(nodeDistPages[i]);
756  ABC_FREE(nodeDistPages);
757  st__free_table(pathTable);
758  return;
759  }
760  *(currentQueuePage + queuePageIndex) = child;
761  queuePageIndex++;
762 
763  childrenCount++;
764  } else {
765  /* if not been met in a path with this parity before */
766  /* put in list */
767  if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist ==
768  MAXSHORTINT)) || ((!Cudd_IsComplement(child)) &&
769  (nodeStat->evenTopDist == MAXSHORTINT))) {
770 
772  if (memOut) {
773  for (i = 0; i <= nodeDistPage; i++)
774  ABC_FREE(nodeDistPages[i]);
775  ABC_FREE(nodeDistPages);
776  st__free_table(pathTable);
777  return;
778 
779  }
780  *(currentQueuePage + queuePageIndex) = child;
781  queuePageIndex++;
782 
783  /* update the distance with the appropriate parity */
784  if (Cudd_IsComplement(child)) {
785  nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
786  } else {
787  nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
788  }
789  childrenCount++;
790  }
791 
792  } /* end of else (not found in st__table) */
793  } /*end of if Not constant child */
794  processingDone--;
795  } /*end of while processing Nv, Nnv */
796  } /*end of while numParents */
797 
798 #ifdef DD_DEBUG
799  assert(queuePages[parentPage] == childPage);
800  assert(parentQueueIndex == childQueueIndex);
801 #endif
802 
803  if (childrenCount != 0) {
804  topLen++;
805  childPage = currentQueuePage;
806  childQueueIndex = queuePageIndex;
807  CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen,
808  childPage, childQueueIndex, childrenCount, fp);
809  }
810 
811  return;
812 
813 } /* end of CreateTopDist */
814 
815 
816 /**Function********************************************************************
817 
818  Synopsis [ Labels each node with the shortest distance from the constant.]
819 
820  Description [Labels each node with the shortest distance from the constant.
821  This is done in a DFS search of the BDD. Each node has an odd
822  and even parity distance from the sink (since there exists paths to both
823  zero and one) which is less than MAXSHORTINT. At each node these distances
824  are updated using the minimum distance of its children from the constant.
825  SInce now both the length from the root and child is known, the minimum path
826  length(length of the shortest path between the root and the constant that
827  this node lies on) of this node can be calculated and used to update the
828  pathLengthArray]
829 
830  SideEffects [Updates Path Table and path length array]
831 
832  SeeAlso [CreatePathTable CreateTopDist AssessPathLength]
833 
834 ******************************************************************************/
835 static int
837  DdNode * node /* current node */,
838  st__table * pathTable /* path table with path lengths */,
839  unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */,
840  FILE *fp /* where to write messages */)
841 {
842  DdNode *N, *Nv, *Nnv;
843  DdNode *realChild;
844  DdNode *child, *regChild;
845  NodeDist_t *nodeStat, *nodeStatChild;
846  unsigned int oddLen, evenLen, pathLength;
847  DdHalfWord botDist;
848  int processingDone;
849 
850  if (Cudd_IsConstant(node))
851  return(1);
852  N = Cudd_Regular(node);
853  /* each node has one table entry */
854  /* update as you go down the min dist of each node from
855  the root in each (odd and even) parity */
856  if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
857  fprintf(fp, "Something wrong, the entry doesn't exist\n");
858  return(0);
859  }
860 
861  /* compute length of odd parity distances */
862  if ((nodeStat->oddTopDist != MAXSHORTINT) &&
863  (nodeStat->oddBotDist != MAXSHORTINT))
864  oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
865  else
866  oddLen = MAXSHORTINT;
867 
868  /* compute length of even parity distances */
869  if (!((nodeStat->evenTopDist == MAXSHORTINT) ||
870  (nodeStat->evenBotDist == MAXSHORTINT)))
871  evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
872  else
873  evenLen = MAXSHORTINT;
874 
875  /* assign pathlength to minimum of the two */
876  pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
877 
878  Nv = Cudd_T(N);
879  Nnv = Cudd_E(N);
880 
881  /* process each child */
882  processingDone = 0;
883  while (processingDone != 2) {
884  if (!processingDone) {
885  child = Nv;
886  } else {
887  child = Nnv;
888  }
889 
890  realChild = Cudd_NotCond(child, Cudd_IsComplement(node));
891  regChild = Cudd_Regular(child);
892  if (Cudd_IsConstant(realChild)) {
893  /* Found a minterm; count parity and shortest distance
894  ** from the constant.
895  */
896  if (Cudd_IsComplement(child))
897  nodeStat->oddBotDist = 1;
898  else
899  nodeStat->evenBotDist = 1;
900  } else {
901  /* If node not in table, recur. */
902  if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStatChild)) {
903  fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n");
904  return(0);
905  }
906 
907  if (nodeStatChild->oddBotDist == MAXSHORTINT) {
908  if (nodeStatChild->evenBotDist == MAXSHORTINT) {
909  if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp))
910  return(0);
911  } else {
912  fprintf(fp, "Something wrong, both bot nodeStats should be there\n");
913  return(0);
914  }
915  }
916 
917  /* Update shortest distance from the constant depending on
918  ** parity. */
919 
920  if (Cudd_IsComplement(child)) {
921  /* If parity on the edge then add 1 to even distance
922  ** of child to get odd parity distance and add 1 to
923  ** odd distance of child to get even parity
924  ** distance. Change distance of current node only if
925  ** the calculated distance is less than existing
926  ** distance. */
927  if (nodeStatChild->oddBotDist != MAXSHORTINT)
928  botDist = nodeStatChild->oddBotDist + 1;
929  else
930  botDist = MAXSHORTINT;
931  if (nodeStat->evenBotDist > botDist )
932  nodeStat->evenBotDist = botDist;
933 
934  if (nodeStatChild->evenBotDist != MAXSHORTINT)
935  botDist = nodeStatChild->evenBotDist + 1;
936  else
937  botDist = MAXSHORTINT;
938  if (nodeStat->oddBotDist > botDist)
939  nodeStat->oddBotDist = botDist;
940 
941  } else {
942  /* If parity on the edge then add 1 to even distance
943  ** of child to get even parity distance and add 1 to
944  ** odd distance of child to get odd parity distance.
945  ** Change distance of current node only if the
946  ** calculated distance is lesser than existing
947  ** distance. */
948  if (nodeStatChild->evenBotDist != MAXSHORTINT)
949  botDist = nodeStatChild->evenBotDist + 1;
950  else
951  botDist = MAXSHORTINT;
952  if (nodeStat->evenBotDist > botDist)
953  nodeStat->evenBotDist = botDist;
954 
955  if (nodeStatChild->oddBotDist != MAXSHORTINT)
956  botDist = nodeStatChild->oddBotDist + 1;
957  else
958  botDist = MAXSHORTINT;
959  if (nodeStat->oddBotDist > botDist)
960  nodeStat->oddBotDist = botDist;
961  }
962  } /* end of else (if not constant child ) */
963  processingDone++;
964  } /* end of while processing Nv, Nnv */
965 
966  /* Compute shortest path length on the fly. */
967  if ((nodeStat->oddTopDist != MAXSHORTINT) &&
968  (nodeStat->oddBotDist != MAXSHORTINT))
969  oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
970  else
971  oddLen = MAXSHORTINT;
972 
973  if ((nodeStat->evenTopDist != MAXSHORTINT) &&
974  (nodeStat->evenBotDist != MAXSHORTINT))
975  evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
976  else
977  evenLen = MAXSHORTINT;
978 
979  /* Update path length array that has number of nodes of a particular
980  ** path length. */
981  if (oddLen < pathLength ) {
982  if (pathLength != MAXSHORTINT)
983  pathLengthArray[pathLength]--;
984  if (oddLen != MAXSHORTINT)
985  pathLengthArray[oddLen]++;
986  pathLength = oddLen;
987  }
988  if (evenLen < pathLength ) {
989  if (pathLength != MAXSHORTINT)
990  pathLengthArray[pathLength]--;
991  if (evenLen != MAXSHORTINT)
992  pathLengthArray[evenLen]++;
993  }
994 
995  return(1);
996 
997 } /*end of CreateBotDist */
998 
999 
1000 /**Function********************************************************************
1001 
1002  Synopsis [ The outer procedure to label each node with its shortest
1003  distance from the root and constant]
1004 
1005  Description [ The outer procedure to label each node with its shortest
1006  distance from the root and constant. Calls CreateTopDist and CreateBotDist.
1007  The basis for computing the distance between root and constant is that
1008  the distance may be the sum of even distances from the node to the root
1009  and constant or the sum of odd distances from the node to the root and
1010  constant. Both CreateTopDist and CreateBotDist create the odd and
1011  even parity distances from the root and constant respectively.]
1012 
1013  SideEffects [None]
1014 
1015  SeeAlso [CreateTopDist CreateBotDist]
1016 
1017 ******************************************************************************/
1018 static st__table *
1020  DdNode * node /* root of function */,
1021  unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */,
1022  FILE *fp /* where to write messages */)
1023 {
1024 
1025  st__table *pathTable;
1026  NodeDist_t *nodeStat;
1027  DdHalfWord topLen;
1028  DdNode *N;
1029  int i, numParents;
1030  int insertValue;
1031  DdNode **childPage;
1032  int parentPage;
1033  int childQueueIndex, parentQueueIndex;
1034 
1035  /* Creating path Table for storing data about nodes */
1036  pathTable = st__init_table( st__ptrcmp, st__ptrhash);
1037 
1038  /* initializing pages for info about each node */
1040  nodeDistPages = ABC_ALLOC(NodeDist_t *, maxNodeDistPages);
1041  if (nodeDistPages == NULL) {
1042  goto OUT_OF_MEM;
1043  }
1044  nodeDistPage = 0;
1045  currentNodeDistPage = nodeDistPages[nodeDistPage] =
1047  if (currentNodeDistPage == NULL) {
1048  for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
1049  ABC_FREE(nodeDistPages);
1050  goto OUT_OF_MEM;
1051  }
1052  nodeDistPageIndex = 0;
1053 
1054  /* Initializing pages for the BFS search queue, implemented as an array. */
1056  queuePages = ABC_ALLOC(DdNode **, maxQueuePages);
1057  if (queuePages == NULL) {
1058  goto OUT_OF_MEM;
1059  }
1060  queuePage = 0;
1061  currentQueuePage = queuePages[queuePage] = ABC_ALLOC(DdNode *, queuePageSize);
1062  if (currentQueuePage == NULL) {
1063  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
1064  ABC_FREE(queuePages);
1065  goto OUT_OF_MEM;
1066  }
1067  queuePageIndex = 0;
1068 
1069  /* Enter the root node into the queue to start with. */
1070  parentPage = queuePage;
1071  parentQueueIndex = queuePageIndex;
1072  topLen = 0;
1073  *(currentQueuePage + queuePageIndex) = node;
1074  queuePageIndex++;
1075  childPage = currentQueuePage;
1076  childQueueIndex = queuePageIndex;
1077 
1078  N = Cudd_Regular(node);
1079 
1081  if (memOut) {
1082  for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
1083  ABC_FREE(nodeDistPages);
1084  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
1085  ABC_FREE(queuePages);
1086  st__free_table(pathTable);
1087  goto OUT_OF_MEM;
1088  }
1089 
1090  nodeStat = currentNodeDistPage + nodeDistPageIndex;
1091  nodeDistPageIndex++;
1092 
1093  nodeStat->oddTopDist = MAXSHORTINT;
1094  nodeStat->evenTopDist = MAXSHORTINT;
1095  nodeStat->evenBotDist = MAXSHORTINT;
1096  nodeStat->oddBotDist = MAXSHORTINT;
1097  nodeStat->regResult = NULL;
1098  nodeStat->compResult = NULL;
1099 
1100  insertValue = st__insert(pathTable, (char *)N, (char *)nodeStat);
1101  if (insertValue == st__OUT_OF_MEM) {
1102  memOut = 1;
1103  for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]);
1104  ABC_FREE(nodeDistPages);
1105  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
1106  ABC_FREE(queuePages);
1107  st__free_table(pathTable);
1108  goto OUT_OF_MEM;
1109  } else if (insertValue == 1) {
1110  fprintf(fp, "Something wrong, the entry exists but didnt show up in st__lookup\n");
1111  return(NULL);
1112  }
1113 
1114  if (Cudd_IsComplement(node)) {
1115  nodeStat->oddTopDist = 0;
1116  } else {
1117  nodeStat->evenTopDist = 0;
1118  }
1119  numParents = 1;
1120  /* call the function that counts the distance of each node from the
1121  * root
1122  */
1123 #ifdef DD_DEBUG
1124  numCalls = 0;
1125 #endif
1126  CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen,
1127  childPage, childQueueIndex, numParents, fp);
1128  if (memOut) {
1129  fprintf(fp, "Out of Memory and cant count path lengths\n");
1130  goto OUT_OF_MEM;
1131  }
1132 
1133 #ifdef DD_DEBUG
1134  numCalls = 0;
1135 #endif
1136  /* call the function that counts the distance of each node from the
1137  * constant
1138  */
1139  if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL);
1140 
1141  /* free BFS queue pages as no longer required */
1142  for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]);
1143  ABC_FREE(queuePages);
1144  return(pathTable);
1145 
1146 OUT_OF_MEM:
1147  (void) fprintf(fp, "Out of Memory, cannot allocate pages\n");
1148  memOut = 1;
1149  return(NULL);
1150 
1151 } /*end of CreatePathTable */
1152 
1153 
1154 /**Function********************************************************************
1155 
1156  Synopsis [Chooses the maximum allowable path length of nodes under the
1157  threshold.]
1158 
1159  Description [Chooses the maximum allowable path length under each node.
1160  The corner cases are when the threshold is larger than the number
1161  of nodes in the BDD iself, in which case 'numVars + 1' is returned.
1162  If all nodes of a particular path length are needed, then the
1163  maxpath returned is the next one with excess nodes = 0;]
1164 
1165  SideEffects [None]
1166 
1167  SeeAlso []
1168 
1169 ******************************************************************************/
1170 static unsigned int
1172  unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */,
1173  int threshold /* threshold to determine maximum allowable nodes in the subset */,
1174  int numVars /* maximum number of variables */,
1175  unsigned int * excess /* number of nodes labeled maxpath required in the subset */,
1176  FILE *fp /* where to write messages */)
1177 {
1178  unsigned int i, maxpath;
1179  int temp;
1180 
1181  temp = threshold;
1182  i = 0;
1183  maxpath = 0;
1184  /* quit loop if i reaches max number of variables or if temp reaches
1185  * below zero
1186  */
1187  while ((i < (unsigned) numVars+1) && (temp > 0)) {
1188  if (pathLengthArray[i] > 0) {
1189  maxpath = i;
1190  temp = temp - pathLengthArray[i];
1191  }
1192  i++;
1193  }
1194  /* if all nodes of max path are needed */
1195  if (temp >= 0) {
1196  maxpath++; /* now maxpath becomes the next maxppath or max number
1197  of variables */
1198  *excess = 0;
1199  } else { /* normal case when subset required is less than size of
1200  original BDD */
1201  *excess = temp + pathLengthArray[maxpath];
1202  }
1203 
1204  if (maxpath == 0) {
1205  fprintf(fp, "Path Length array seems to be all zeroes, check\n");
1206  }
1207  return(maxpath);
1208 
1209 } /* end of AssessPathLength */
1210 
1211 
1212 /**Function********************************************************************
1213 
1214  Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath]
1215 
1216  Description [Builds the BDD with nodes labeled with path length
1217  under maxpath and as many nodes labeled maxpath as determined by the
1218  threshold. The procedure uses the path table to determine which nodes
1219  in the original bdd need to be retained. This procedure picks a
1220  shortest path (tie break decided by taking the child with the shortest
1221  distance to the constant) and recurs down the path till it reaches the
1222  constant. the procedure then starts building the subset upward from
1223  the constant. All nodes labeled by path lengths less than the given
1224  maxpath are used to build the subset. However, in the case of nodes
1225  that have label equal to maxpath, as many are chosen as required by
1226  the threshold. This number is stored in the info structure in the
1227  field thresholdReached. This field is decremented whenever a node
1228  labeled maxpath is encountered and the nodes labeled maxpath are
1229  aggregated in a maxpath table. As soon as the thresholdReached count
1230  goes to 0, the shortest path from this node to the constant is found.
1231  The extraction of nodes with the above labeling is based on the fact
1232  that each node, labeled with a path length, P, has at least one child
1233  labeled P or less. So extracting all nodes labeled a given path length
1234  P ensures complete paths between the root and the constant. Extraction
1235  of a partial number of nodes with a given path length may result in
1236  incomplete paths and hence the additional number of nodes are grabbed
1237  to complete the path. Since the Bdd is built bottom-up, other nodes
1238  labeled maxpath do lie on complete paths. The procedure may cause the
1239  subset to have a larger or smaller number of nodes than the specified
1240  threshold. The increase in the number of nodes is caused by the
1241  building of a subset and the reduction by recombination. However in
1242  most cases, the recombination overshadows the increase and the
1243  procedure returns a result with lower number of nodes than specified.
1244  The subsetNodeTable is NIL when there is no hard limit on the number
1245  of nodes. Further efforts towards keeping the subset closer to the
1246  threshold number were abandoned in favour of keeping the procedure
1247  simple and fast.]
1248 
1249  SideEffects [SubsetNodeTable is changed if it is not NIL.]
1250 
1251  SeeAlso []
1252 
1253 ******************************************************************************/
1254 static DdNode *
1256  DdManager * dd /* DD manager */,
1257  st__table * pathTable /* path table with path lengths and computed results */,
1258  DdNode * node /* current node */,
1259  struct AssortedInfo * info /* assorted information structure */,
1260  st__table * subsetNodeTable /* table storing computed results */)
1261 {
1262  DdNode *N, *Nv, *Nnv;
1263  DdNode *ThenBranch, *ElseBranch, *childBranch;
1264  DdNode *child, *regChild, *regNnv = NULL, *regNv = NULL;
1265  NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv;
1266  DdNode *neW, *topv, *regNew;
1267  char *entry;
1268  unsigned int topid;
1269  unsigned int childPathLength, oddLen, evenLen, NnvPathLength = 0, NvPathLength = 0;
1270  unsigned int NvBotDist, NnvBotDist;
1271  int tiebreakChild;
1272  int processingDone, thenDone, elseDone;
1273 
1274 
1275 #ifdef DD_DEBUG
1276  numCalls++;
1277 #endif
1278  if (Cudd_IsConstant(node))
1279  return(node);
1280 
1281  N = Cudd_Regular(node);
1282  /* Find node in table. */
1283  if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) {
1284  (void) fprintf(dd->err, "Something wrong, node must be in table \n");
1286  return(NULL);
1287  }
1288  /* If the node in the table has been visited, then return the corresponding
1289  ** Dd. Since a node can become a subset of itself, its
1290  ** complement (that is te same node reached by a different parity) will
1291  ** become a superset of the original node and result in some minterms
1292  ** that were not in the original set. Hence two different results are
1293  ** maintained, corresponding to the odd and even parities.
1294  */
1295 
1296  /* If this node is reached with an odd parity, get odd parity results. */
1297  if (Cudd_IsComplement(node)) {
1298  if (nodeStat->compResult != NULL) {
1299 #ifdef DD_DEBUG
1300  hits++;
1301 #endif
1302  return(nodeStat->compResult);
1303  }
1304  } else {
1305  /* if this node is reached with an even parity, get even parity
1306  * results
1307  */
1308  if (nodeStat->regResult != NULL) {
1309 #ifdef DD_DEBUG
1310  hits++;
1311 #endif
1312  return(nodeStat->regResult);
1313  }
1314  }
1315 
1316 
1317  /* get children */
1318  Nv = Cudd_T(N);
1319  Nnv = Cudd_E(N);
1320 
1321  Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
1322  Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
1323 
1324  /* no child processed */
1325  processingDone = 0;
1326  /* then child not processed */
1327  thenDone = 0;
1328  ThenBranch = NULL;
1329  /* else child not processed */
1330  elseDone = 0;
1331  ElseBranch = NULL;
1332  /* if then child constant, branch is the child */
1333  if (Cudd_IsConstant(Nv)) {
1334  /*shortest path found */
1335  if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) {
1336  info->findShortestPath = 0;
1337  }
1338 
1339  ThenBranch = Nv;
1340  cuddRef(ThenBranch);
1341  if (ThenBranch == NULL) {
1342  return(NULL);
1343  }
1344 
1345  thenDone++;
1346  processingDone++;
1347  NvBotDist = MAXSHORTINT;
1348  } else {
1349  /* Derive regular child for table lookup. */
1350  regNv = Cudd_Regular(Nv);
1351  /* Get node data for shortest path length. */
1352  if (! st__lookup(pathTable, (const char *)regNv, (char **)&nodeStatNv) ) {
1353  (void) fprintf(dd->err, "Something wrong, node must be in table\n");
1355  return(NULL);
1356  }
1357  /* Derive shortest path length for child. */
1358  if ((nodeStatNv->oddTopDist != MAXSHORTINT) &&
1359  (nodeStatNv->oddBotDist != MAXSHORTINT)) {
1360  oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist);
1361  } else {
1362  oddLen = MAXSHORTINT;
1363  }
1364 
1365  if ((nodeStatNv->evenTopDist != MAXSHORTINT) &&
1366  (nodeStatNv->evenBotDist != MAXSHORTINT)) {
1367  evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist);
1368  } else {
1369  evenLen = MAXSHORTINT;
1370  }
1371 
1372  NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
1373  NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist:
1374  nodeStatNv->evenBotDist;
1375  }
1376  /* if else child constant, branch is the child */
1377  if (Cudd_IsConstant(Nnv)) {
1378  /*shortest path found */
1379  if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) {
1380  info->findShortestPath = 0;
1381  }
1382 
1383  ElseBranch = Nnv;
1384  cuddRef(ElseBranch);
1385  if (ElseBranch == NULL) {
1386  return(NULL);
1387  }
1388 
1389  elseDone++;
1390  processingDone++;
1391  NnvBotDist = MAXSHORTINT;
1392  } else {
1393  /* Derive regular child for table lookup. */
1394  regNnv = Cudd_Regular(Nnv);
1395  /* Get node data for shortest path length. */
1396  if (! st__lookup(pathTable, (const char *)regNnv, (char **)&nodeStatNnv) ) {
1397  (void) fprintf(dd->err, "Something wrong, node must be in table\n");
1399  return(NULL);
1400  }
1401  /* Derive shortest path length for child. */
1402  if ((nodeStatNnv->oddTopDist != MAXSHORTINT) &&
1403  (nodeStatNnv->oddBotDist != MAXSHORTINT)) {
1404  oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist);
1405  } else {
1406  oddLen = MAXSHORTINT;
1407  }
1408 
1409  if ((nodeStatNnv->evenTopDist != MAXSHORTINT) &&
1410  (nodeStatNnv->evenBotDist != MAXSHORTINT)) {
1411  evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist);
1412  } else {
1413  evenLen = MAXSHORTINT;
1414  }
1415 
1416  NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
1417  NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist :
1418  nodeStatNnv->evenBotDist;
1419  }
1420 
1421  tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0;
1422  /* while both children not processed */
1423  while (processingDone != 2) {
1424  if (!processingDone) {
1425  /* if no child processed */
1426  /* pick the child with shortest path length and record which one
1427  * picked
1428  */
1429  if ((NvPathLength < NnvPathLength) ||
1430  ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) {
1431  child = Nv;
1432  regChild = regNv;
1433  thenDone = 1;
1434  childPathLength = NvPathLength;
1435  } else {
1436  child = Nnv;
1437  regChild = regNnv;
1438  elseDone = 1;
1439  childPathLength = NnvPathLength;
1440  } /* then path length less than else path length */
1441  } else {
1442  /* if one child processed, process the other */
1443  if (thenDone) {
1444  child = Nnv;
1445  regChild = regNnv;
1446  elseDone = 1;
1447  childPathLength = NnvPathLength;
1448  } else {
1449  child = Nv;
1450  regChild = regNv;
1451  thenDone = 1;
1452  childPathLength = NvPathLength;
1453  } /* end of else pick the Then child if ELSE child processed */
1454  } /* end of else one child has been processed */
1455 
1456  /* ignore (replace with constant 0) all nodes which lie on paths larger
1457  * than the maximum length of the path required
1458  */
1459  if (childPathLength > info->maxpath) {
1460  /* record nodes visited */
1461  childBranch = zero;
1462  } else {
1463  if (childPathLength < info->maxpath) {
1464  if (info->findShortestPath) {
1465  info->findShortestPath = 0;
1466  }
1467  childBranch = BuildSubsetBdd(dd, pathTable, child, info,
1468  subsetNodeTable);
1469 
1470  } else { /* Case: path length of node = maxpath */
1471  /* If the node labeled with maxpath is found in the
1472  ** maxpathTable, use it to build the subset BDD. */
1473  if ( st__lookup(info->maxpathTable, (char *)regChild,
1474  (char **)&entry)) {
1475  /* When a node that is already been chosen is hit,
1476  ** the quest for a complete path is over. */
1477  if (info->findShortestPath) {
1478  info->findShortestPath = 0;
1479  }
1480  childBranch = BuildSubsetBdd(dd, pathTable, child, info,
1481  subsetNodeTable);
1482  } else {
1483  /* If node is not found in the maxpathTable and
1484  ** the threshold has been reached, then if the
1485  ** path needs to be completed, continue. Else
1486  ** replace the node with a zero. */
1487  if (info->thresholdReached <= 0) {
1488  if (info->findShortestPath) {
1489  if ( st__insert(info->maxpathTable, (char *)regChild,
1490  (char *)NIL(char)) == st__OUT_OF_MEM) {
1491  memOut = 1;
1492  (void) fprintf(dd->err, "OUT of memory\n");
1493  info->thresholdReached = 0;
1494  childBranch = zero;
1495  } else {
1496  info->thresholdReached--;
1497  childBranch = BuildSubsetBdd(dd, pathTable,
1498  child, info,subsetNodeTable);
1499  }
1500  } else { /* not find shortest path, we dont need this
1501  node */
1502  childBranch = zero;
1503  }
1504  } else { /* Threshold hasn't been reached,
1505  ** need the node. */
1506  if ( st__insert(info->maxpathTable, (char *)regChild,
1507  (char *)NIL(char)) == st__OUT_OF_MEM) {
1508  memOut = 1;
1509  (void) fprintf(dd->err, "OUT of memory\n");
1510  info->thresholdReached = 0;
1511  childBranch = zero;
1512  } else {
1513  info->thresholdReached--;
1514  if (info->thresholdReached <= 0) {
1515  info->findShortestPath = 1;
1516  }
1517  childBranch = BuildSubsetBdd(dd, pathTable,
1518  child, info, subsetNodeTable);
1519 
1520  } /* end of st__insert successful */
1521  } /* end of threshold hasnt been reached yet */
1522  } /* end of else node not found in maxpath table */
1523  } /* end of if (path length of node = maxpath) */
1524  } /* end if !(childPathLength > maxpath) */
1525  if (childBranch == NULL) {
1526  /* deref other stuff incase reordering has taken place */
1527  if (ThenBranch != NULL) {
1528  Cudd_RecursiveDeref(dd, ThenBranch);
1529  ThenBranch = NULL;
1530  }
1531  if (ElseBranch != NULL) {
1532  Cudd_RecursiveDeref(dd, ElseBranch);
1533  ElseBranch = NULL;
1534  }
1535  return(NULL);
1536  }
1537 
1538  cuddRef(childBranch);
1539 
1540  if (child == Nv) {
1541  ThenBranch = childBranch;
1542  } else {
1543  ElseBranch = childBranch;
1544  }
1545  processingDone++;
1546 
1547  } /*end of while processing Nv, Nnv */
1548 
1549  info->findShortestPath = 0;
1550  topid = Cudd_NodeReadIndex(N);
1551  topv = Cudd_ReadVars(dd, topid);
1552  cuddRef(topv);
1553  neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
1554  if (neW != NULL) {
1555  cuddRef(neW);
1556  }
1557  Cudd_RecursiveDeref(dd, topv);
1558  Cudd_RecursiveDeref(dd, ThenBranch);
1559  Cudd_RecursiveDeref(dd, ElseBranch);
1560 
1561 
1562  /* Hard Limit of threshold has been imposed */
1563  if (subsetNodeTable != NIL( st__table)) {
1564  /* check if a new node is created */
1565  regNew = Cudd_Regular(neW);
1566  /* subset node table keeps all new nodes that have been created to keep
1567  * a running count of how many nodes have been built in the subset.
1568  */
1569  if (! st__lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) {
1570  if (!Cudd_IsConstant(regNew)) {
1571  if ( st__insert(subsetNodeTable, (char *)regNew,
1572  (char *)NULL) == st__OUT_OF_MEM) {
1573  (void) fprintf(dd->err, "Out of memory\n");
1574  return (NULL);
1575  }
1576  if ( st__count(subsetNodeTable) > info->threshold) {
1577  info->thresholdReached = 0;
1578  }
1579  }
1580  }
1581  }
1582 
1583 
1584  if (neW == NULL) {
1585  return(NULL);
1586  } else {
1587  /*store computed result in regular form*/
1588  if (Cudd_IsComplement(node)) {
1589  nodeStat->compResult = neW;
1590  cuddRef(nodeStat->compResult);
1591  /* if the new node is the same as the corresponding node in the
1592  * original bdd then its complement need not be computed as it
1593  * cannot be larger than the node itself
1594  */
1595  if (neW == node) {
1596 #ifdef DD_DEBUG
1597  thishit++;
1598 #endif
1599  /* if a result for the node has already been computed, then
1600  * it can only be smaller than teh node itself. hence store
1601  * the node result in order not to break recombination
1602  */
1603  if (nodeStat->regResult != NULL) {
1604  Cudd_RecursiveDeref(dd, nodeStat->regResult);
1605  }
1606  nodeStat->regResult = Cudd_Not(neW);
1607  cuddRef(nodeStat->regResult);
1608  }
1609 
1610  } else {
1611  nodeStat->regResult = neW;
1612  cuddRef(nodeStat->regResult);
1613  if (neW == node) {
1614 #ifdef DD_DEBUG
1615  thishit++;
1616 #endif
1617  if (nodeStat->compResult != NULL) {
1618  Cudd_RecursiveDeref(dd, nodeStat->compResult);
1619  }
1620  nodeStat->compResult = Cudd_Not(neW);
1621  cuddRef(nodeStat->compResult);
1622  }
1623  }
1624 
1625  cuddDeref(neW);
1626  return(neW);
1627  } /* end of else i.e. Subset != NULL */
1628 } /* end of BuildSubsetBdd */
1629 
1630 
1631 /**Function********************************************************************
1632 
1633  Synopsis [Procedure to free te result dds stored in the NodeDist pages.]
1634 
1635  Description [None]
1636 
1637  SideEffects [None]
1638 
1639  SeeAlso []
1640 
1641 ******************************************************************************/
1642 static enum st__retval
1644  char * key,
1645  char * value,
1646  char * arg)
1647 {
1648  NodeDist_t *nodeStat;
1649  DdManager *dd;
1650 
1651  nodeStat = (NodeDist_t *)value;
1652  dd = (DdManager *)arg;
1653  if (nodeStat->regResult != NULL) {
1654  Cudd_RecursiveDeref(dd, nodeStat->regResult);
1655  }
1656  if (nodeStat->compResult != NULL) {
1657  Cudd_RecursiveDeref(dd, nodeStat->compResult);
1658  }
1659  return( st__CONTINUE);
1660 
1661 } /* end of stPathTableFree */
1662 
1663 
1665 
static int queuePageIndex
Definition: cuddSubsetSP.c:150
DdHalfWord oddBotDist
Definition: cuddSubsetSP.c:103
void st__free_table(st__table *table)
Definition: st.c:81
#define cuddRef(n)
Definition: cuddInt.h:584
static void ResizeNodeDistPages(void)
Definition: cuddSubsetSP.c:512
static int nodeDistPageSize
Definition: cuddSubsetSP.c:145
#define Cudd_T(node)
Definition: cudd.h:440
unsigned short DdHalfWord
Definition: cudd.h:262
static int nodeDistPageIndex
Definition: cuddSubsetSP.c:143
static DdNode * zero
Definition: cuddSubsetSP.c:140
#define DEFAULT_NODE_DIST_PAGE_SIZE
Definition: cuddSubsetSP.c:83
#define cuddDeref(n)
Definition: cuddInt.h:604
st__table * maxpathTable
Definition: cuddSubsetSP.c:114
#define Cudd_E(node)
Definition: cudd.h:455
DdNode * cuddSubsetShortPaths(DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
Definition: cuddSubsetSP.c:316
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
static NodeDist_t * currentNodeDistPage
Definition: cuddSubsetSP.c:147
#define Cudd_Not(node)
Definition: cudd.h:367
int st__insert(st__table *table, const char *key, char *value)
Definition: st.c:171
#define Cudd_IsConstant(node)
Definition: cudd.h:352
#define Cudd_Regular(node)
Definition: cudd.h:397
int st__ptrcmp(const char *, const char *)
Definition: st.c:480
FILE * err
Definition: cuddInt.h:442
static int memOut
Definition: cuddSubsetSP.c:139
DdHalfWord oddTopDist
Definition: cuddSubsetSP.c:101
#define INITIAL_PAGES
Definition: cuddSubsetSP.c:89
#define MAXSHORTINT
Definition: cuddSubsetSP.c:84
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
static char rcsid[] DD_UNUSED
Definition: cuddSubsetSP.c:129
DdNode * Cudd_ReadVars(DdManager *dd, int i)
Definition: cuddAPI.c:2407
static DdNode ** currentQueuePage
Definition: cuddSubsetSP.c:154
int Cudd_ReadSize(DdManager *dd)
Definition: cuddAPI.c:1441
#define NIL(type)
Definition: avl.h:25
static int * entry
Definition: cuddGroup.c:122
static void check(int expr)
Definition: satSolver.c:46
DdNode * Cudd_bddIteConstant(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddBddIte.c:174
st__retval
Definition: st.h:73
st__table * st__init_table(st__compare_func_type compare, st__hash_func_type hash)
Definition: st.c:72
DdNode * compResult
Definition: cuddSubsetSP.c:106
unsigned int maxpath
Definition: cuddSubsetSP.c:111
int reordered
Definition: cuddInt.h:409
static int CreateBotDist(DdNode *node, st__table *pathTable, unsigned int *pathLengthArray, FILE *fp)
Definition: cuddSubsetSP.c:836
#define Cudd_IsComplement(node)
Definition: cudd.h:425
#define st__count(table)
Definition: st.h:71
static DdNode *** queuePages
Definition: cuddSubsetSP.c:149
static void ResizeQueuePages(void)
Definition: cuddSubsetSP.c:574
FILE * out
Definition: cuddInt.h:441
static int maxNodeDistPages
Definition: cuddSubsetSP.c:146
static int maxQueuePages
Definition: cuddSubsetSP.c:153
Definition: st.h:52
DdNode * regResult
Definition: cuddSubsetSP.c:105
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
int thresholdReached
Definition: cuddSubsetSP.c:113
static int queuePageSize
Definition: cuddSubsetSP.c:152
#define DEFAULT_PAGE_SIZE
Definition: cuddSubsetSP.c:82
int st__foreach(st__table *table, enum st__retval(*func)(char *, char *, char *), char *arg)
Definition: st.c:421
static int nodeDistPage
Definition: cuddSubsetSP.c:144
int findShortestPath
Definition: cuddSubsetSP.c:112
#define st__OUT_OF_MEM
Definition: st.h:113
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
static enum st__retval stPathTableDdFree(char *key, char *value, char *arg)
DdHalfWord evenBotDist
Definition: cuddSubsetSP.c:104
int st__lookup(st__table *table, const char *key, char **value)
Definition: st.c:114
static unsigned int AssessPathLength(unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)
DdNode * Cudd_SubsetShortPaths(DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
Definition: cuddSubsetSP.c:220
DdNode * Cudd_SupersetShortPaths(DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
Definition: cuddSubsetSP.c:272
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int Cudd_NodeReadIndex(DdNode *node)
Definition: cuddAPI.c:2277
static int queuePage
Definition: cuddSubsetSP.c:151
enum keys key
#define Cudd_NotCond(node, c)
Definition: cudd.h:383
int value
#define assert(ex)
Definition: util_old.h:213
DdHalfWord evenTopDist
Definition: cuddSubsetSP.c:102
#define DD_ONE(dd)
Definition: cuddInt.h:911
static st__table * CreatePathTable(DdNode *node, unsigned int *pathLengthArray, FILE *fp)
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
int st__ptrhash(const char *, int)
Definition: st.c:468
static DdNode * one
Definition: cuddSubsetSP.c:140
static NodeDist_t ** nodeDistPages
Definition: cuddSubsetSP.c:142
static void CreateTopDist(st__table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp)
Definition: cuddSubsetSP.c:635
static DdNode * BuildSubsetBdd(DdManager *dd, st__table *pathTable, DdNode *node, struct AssortedInfo *info, st__table *subsetNodeTable)
DdNode * cuddBddIteRecur(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddBddIte.c:633