SVF
cuddLinear.c
Go to the documentation of this file.
1 
64 #include "CUDD/util.h"
65 #include "CUDD/cuddInt.h"
66 
67 /*---------------------------------------------------------------------------*/
68 /* Constant declarations */
69 /*---------------------------------------------------------------------------*/
70 
71 #define CUDD_SWAP_MOVE 0
72 #define CUDD_LINEAR_TRANSFORM_MOVE 1
73 #define CUDD_INVERSE_TRANSFORM_MOVE 2
74 #if SIZEOF_LONG == 8
75 #define BPL 64
76 #define LOGBPL 6
77 #else
78 #define BPL 32
79 #define LOGBPL 5
80 #endif
81 
82 /*---------------------------------------------------------------------------*/
83 /* Stucture declarations */
84 /*---------------------------------------------------------------------------*/
85 
86 /*---------------------------------------------------------------------------*/
87 /* Type declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 /*---------------------------------------------------------------------------*/
91 /* Variable declarations */
92 /*---------------------------------------------------------------------------*/
93 
94 #ifndef lint
95 static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.29 2012/02/05 01:07:19 fabio Exp $";
96 #endif
97 
98 static int *entry;
99 
100 #ifdef DD_STATS
101 extern int ddTotalNumberSwapping;
102 extern int ddTotalNISwaps;
103 static int ddTotalNumberLinearTr;
104 #endif
105 
106 #ifdef DD_DEBUG
107 static int zero = 0;
108 #endif
109 
110 /*---------------------------------------------------------------------------*/
111 /* Macro declarations */
112 /*---------------------------------------------------------------------------*/
113 
116 /*---------------------------------------------------------------------------*/
117 /* Static function prototypes */
118 /*---------------------------------------------------------------------------*/
119 
120 static int ddLinearUniqueCompare (int *ptrX, int *ptrY);
121 static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh);
122 static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves);
123 static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves);
124 static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves);
125 static Move* ddUndoMoves (DdManager *table, Move *moves);
126 static void cuddXorLinear (DdManager *table, int x, int y);
127 
131 /*---------------------------------------------------------------------------*/
132 /* Definition of exported functions */
133 /*---------------------------------------------------------------------------*/
134 
135 
148 int
150  DdManager * table)
151 {
152  int i,j,k;
153  int retval;
154  int nvars = table->linearSize;
155  int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
156  long word;
157 
158  for (i = 0; i < nvars; i++) {
159  for (j = 0; j < wordsPerRow; j++) {
160  word = table->linear[i*wordsPerRow + j];
161  for (k = 0; k < BPL; k++) {
162  retval = fprintf(table->out,"%ld",word & 1);
163  if (retval == 0) return(0);
164  word >>= 1;
165  }
166  }
167  retval = fprintf(table->out,"\n");
168  if (retval == 0) return(0);
169  }
170  return(1);
171 
172 } /* end of Cudd_PrintLinear */
173 
174 
186 int
188  DdManager * table /* CUDD manager */,
189  int x /* row index */,
190  int y /* column index */)
191 {
192  int nvars = table->size;
193  int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
194  long word;
195  int bit;
196  int result;
197 
198  assert(table->size == table->linearSize);
199 
200  word = wordsPerRow * x + (y >> LOGBPL);
201  bit = y & (BPL-1);
202  result = (int) ((table->linear[word] >> bit) & 1);
203  return(result);
204 
205 } /* end of Cudd_ReadLinear */
206 
207 
208 /*---------------------------------------------------------------------------*/
209 /* Definition of internal functions */
210 /*---------------------------------------------------------------------------*/
211 
212 
235 int
237  DdManager * table,
238  int lower,
239  int upper)
240 {
241  int i;
242  int *var;
243  int size;
244  int x;
245  int result;
246 #ifdef DD_STATS
247  int previousSize;
248 #endif
249 
250 #ifdef DD_STATS
251  ddTotalNumberLinearTr = 0;
252 #endif
253 
254  size = table->size;
255 
256  var = NULL;
257  entry = NULL;
258  if (table->linear == NULL) {
259  result = cuddInitLinear(table);
260  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
261 #if 0
262  (void) fprintf(table->out,"\n");
263  result = Cudd_PrintLinear(table);
264  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
265 #endif
266  } else if (table->size != table->linearSize) {
267  result = cuddResizeLinear(table);
268  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
269 #if 0
270  (void) fprintf(table->out,"\n");
271  result = Cudd_PrintLinear(table);
272  if (result == 0) goto cuddLinearAndSiftingOutOfMem;
273 #endif
274  }
275 
276  /* Find order in which to sift variables. */
277  entry = ALLOC(int,size);
278  if (entry == NULL) {
279  table->errorCode = CUDD_MEMORY_OUT;
280  goto cuddLinearAndSiftingOutOfMem;
281  }
282  var = ALLOC(int,size);
283  if (var == NULL) {
284  table->errorCode = CUDD_MEMORY_OUT;
285  goto cuddLinearAndSiftingOutOfMem;
286  }
287 
288  for (i = 0; i < size; i++) {
289  x = table->perm[i];
290  entry[i] = table->subtables[x].keys;
291  var[i] = i;
292  }
293 
294  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
295 
296  /* Now sift. */
297  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
298  x = table->perm[var[i]];
299  if (x < lower || x > upper) continue;
300 #ifdef DD_STATS
301  previousSize = table->keys - table->isolated;
302 #endif
303  result = ddLinearAndSiftingAux(table,x,lower,upper);
304  if (!result) goto cuddLinearAndSiftingOutOfMem;
305 #ifdef DD_STATS
306  if (table->keys < (unsigned) previousSize + table->isolated) {
307  (void) fprintf(table->out,"-");
308  } else if (table->keys > (unsigned) previousSize + table->isolated) {
309  (void) fprintf(table->out,"+"); /* should never happen */
310  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
311  } else {
312  (void) fprintf(table->out,"=");
313  }
314  fflush(table->out);
315 #endif
316 #ifdef DD_DEBUG
317  (void) Cudd_DebugCheck(table);
318 #endif
319  }
320 
321  FREE(var);
322  FREE(entry);
323 
324 #ifdef DD_STATS
325  (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
326  ddTotalNumberLinearTr);
327 #endif
328 
329  return(1);
330 
331 cuddLinearAndSiftingOutOfMem:
332 
333  if (entry != NULL) FREE(entry);
334  if (var != NULL) FREE(var);
335 
336  return(0);
337 
338 } /* end of cuddLinearAndSifting */
339 
340 
359 int
361  DdManager * table,
362  int x,
363  int y)
364 {
365  DdNodePtr *xlist, *ylist;
366  int xindex, yindex;
367  int xslots, yslots;
368  int xshift, yshift;
369  int oldxkeys, oldykeys;
370  int newxkeys, newykeys;
371  int comple, newcomplement;
372  int i;
373  int posn;
374  int isolated;
375  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
376  DdNode *g,*next,*last;
377  DdNodePtr *previousP;
378  DdNode *tmp;
379  DdNode *sentinel = &(table->sentinel);
380 #ifdef DD_DEBUG
381  int count, idcheck;
382 #endif
383 
384 #ifdef DD_DEBUG
385  assert(x < y);
386  assert(cuddNextHigh(table,x) == y);
387  assert(table->subtables[x].keys != 0);
388  assert(table->subtables[y].keys != 0);
389  assert(table->subtables[x].dead == 0);
390  assert(table->subtables[y].dead == 0);
391 #endif
392 
393  xindex = table->invperm[x];
394  yindex = table->invperm[y];
395 
396  if (cuddTestInteract(table,xindex,yindex)) {
397 #ifdef DD_STATS
398  ddTotalNumberLinearTr++;
399 #endif
400  /* Get parameters of x subtable. */
401  xlist = table->subtables[x].nodelist;
402  oldxkeys = table->subtables[x].keys;
403  xslots = table->subtables[x].slots;
404  xshift = table->subtables[x].shift;
405 
406  /* Get parameters of y subtable. */
407  ylist = table->subtables[y].nodelist;
408  oldykeys = table->subtables[y].keys;
409  yslots = table->subtables[y].slots;
410  yshift = table->subtables[y].shift;
411 
412  newxkeys = 0;
413  newykeys = oldykeys;
414 
415  /* Check whether the two projection functions involved in this
416  ** swap are isolated. At the end, we'll be able to tell how many
417  ** isolated projection functions are there by checking only these
418  ** two functions again. This is done to eliminate the isolated
419  ** projection functions from the node count.
420  */
421  isolated = - ((table->vars[xindex]->ref == 1) +
422  (table->vars[yindex]->ref == 1));
423 
424  /* The nodes in the x layer are put in a chain.
425  ** The chain is handled as a FIFO; g points to the beginning and
426  ** last points to the end.
427  */
428  g = NULL;
429 #ifdef DD_DEBUG
430  last = NULL;
431 #endif
432  for (i = 0; i < xslots; i++) {
433  f = xlist[i];
434  if (f == sentinel) continue;
435  xlist[i] = sentinel;
436  if (g == NULL) {
437  g = f;
438  } else {
439  last->next = f;
440  }
441  while ((next = f->next) != sentinel) {
442  f = next;
443  } /* while there are elements in the collision chain */
444  last = f;
445  } /* for each slot of the x subtable */
446 #ifdef DD_DEBUG
447  /* last is always assigned in the for loop because there is at
448  ** least one key */
449  assert(last != NULL);
450 #endif
451  last->next = NULL;
452 
453 #ifdef DD_COUNT
454  table->swapSteps += oldxkeys;
455 #endif
456  /* Take care of the x nodes that must be re-expressed.
457  ** They form a linked list pointed by g.
458  */
459  f = g;
460  while (f != NULL) {
461  next = f->next;
462  /* Find f1, f0, f11, f10, f01, f00. */
463  f1 = cuddT(f);
464 #ifdef DD_DEBUG
465  assert(!(Cudd_IsComplement(f1)));
466 #endif
467  if ((int) f1->index == yindex) {
468  f11 = cuddT(f1); f10 = cuddE(f1);
469  } else {
470  f11 = f10 = f1;
471  }
472 #ifdef DD_DEBUG
473  assert(!(Cudd_IsComplement(f11)));
474 #endif
475  f0 = cuddE(f);
476  comple = Cudd_IsComplement(f0);
477  f0 = Cudd_Regular(f0);
478  if ((int) f0->index == yindex) {
479  f01 = cuddT(f0); f00 = cuddE(f0);
480  } else {
481  f01 = f00 = f0;
482  }
483  if (comple) {
484  f01 = Cudd_Not(f01);
485  f00 = Cudd_Not(f00);
486  }
487  /* Decrease ref count of f1. */
488  cuddSatDec(f1->ref);
489  /* Create the new T child. */
490  if (f11 == f00) {
491  newf1 = f11;
492  cuddSatInc(newf1->ref);
493  } else {
494  /* Check ylist for triple (yindex,f11,f00). */
495  posn = ddHash(f11, f00, yshift);
496  /* For each element newf1 in collision list ylist[posn]. */
497  previousP = &(ylist[posn]);
498  newf1 = *previousP;
499  while (f11 < cuddT(newf1)) {
500  previousP = &(newf1->next);
501  newf1 = *previousP;
502  }
503  while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
504  previousP = &(newf1->next);
505  newf1 = *previousP;
506  }
507  if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
508  cuddSatInc(newf1->ref);
509  } else { /* no match */
510  newf1 = cuddDynamicAllocNode(table);
511  if (newf1 == NULL)
512  goto cuddLinearOutOfMem;
513  newf1->index = yindex; newf1->ref = 1;
514  cuddT(newf1) = f11;
515  cuddE(newf1) = f00;
516  /* Insert newf1 in the collision list ylist[posn];
517  ** increase the ref counts of f11 and f00.
518  */
519  newykeys++;
520  newf1->next = *previousP;
521  *previousP = newf1;
522  cuddSatInc(f11->ref);
523  tmp = Cudd_Regular(f00);
524  cuddSatInc(tmp->ref);
525  }
526  }
527  cuddT(f) = newf1;
528 #ifdef DD_DEBUG
529  assert(!(Cudd_IsComplement(newf1)));
530 #endif
531 
532  /* Do the same for f0, keeping complement dots into account. */
533  /* decrease ref count of f0 */
534  tmp = Cudd_Regular(f0);
535  cuddSatDec(tmp->ref);
536  /* create the new E child */
537  if (f01 == f10) {
538  newf0 = f01;
539  tmp = Cudd_Regular(newf0);
540  cuddSatInc(tmp->ref);
541  } else {
542  /* make sure f01 is regular */
543  newcomplement = Cudd_IsComplement(f01);
544  if (newcomplement) {
545  f01 = Cudd_Not(f01);
546  f10 = Cudd_Not(f10);
547  }
548  /* Check ylist for triple (yindex,f01,f10). */
549  posn = ddHash(f01, f10, yshift);
550  /* For each element newf0 in collision list ylist[posn]. */
551  previousP = &(ylist[posn]);
552  newf0 = *previousP;
553  while (f01 < cuddT(newf0)) {
554  previousP = &(newf0->next);
555  newf0 = *previousP;
556  }
557  while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
558  previousP = &(newf0->next);
559  newf0 = *previousP;
560  }
561  if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
562  cuddSatInc(newf0->ref);
563  } else { /* no match */
564  newf0 = cuddDynamicAllocNode(table);
565  if (newf0 == NULL)
566  goto cuddLinearOutOfMem;
567  newf0->index = yindex; newf0->ref = 1;
568  cuddT(newf0) = f01;
569  cuddE(newf0) = f10;
570  /* Insert newf0 in the collision list ylist[posn];
571  ** increase the ref counts of f01 and f10.
572  */
573  newykeys++;
574  newf0->next = *previousP;
575  *previousP = newf0;
576  cuddSatInc(f01->ref);
577  tmp = Cudd_Regular(f10);
578  cuddSatInc(tmp->ref);
579  }
580  if (newcomplement) {
581  newf0 = Cudd_Not(newf0);
582  }
583  }
584  cuddE(f) = newf0;
585 
586  /* Re-insert the modified f in xlist.
587  ** The modified f does not already exists in xlist.
588  ** (Because of the uniqueness of the cofactors.)
589  */
590  posn = ddHash(newf1, newf0, xshift);
591  newxkeys++;
592  previousP = &(xlist[posn]);
593  tmp = *previousP;
594  while (newf1 < cuddT(tmp)) {
595  previousP = &(tmp->next);
596  tmp = *previousP;
597  }
598  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
599  previousP = &(tmp->next);
600  tmp = *previousP;
601  }
602  f->next = *previousP;
603  *previousP = f;
604  f = next;
605  } /* while f != NULL */
606 
607  /* GC the y layer. */
608 
609  /* For each node f in ylist. */
610  for (i = 0; i < yslots; i++) {
611  previousP = &(ylist[i]);
612  f = *previousP;
613  while (f != sentinel) {
614  next = f->next;
615  if (f->ref == 0) {
616  tmp = cuddT(f);
617  cuddSatDec(tmp->ref);
618  tmp = Cudd_Regular(cuddE(f));
619  cuddSatDec(tmp->ref);
620  cuddDeallocNode(table,f);
621  newykeys--;
622  } else {
623  *previousP = f;
624  previousP = &(f->next);
625  }
626  f = next;
627  } /* while f */
628  *previousP = sentinel;
629  } /* for every collision list */
630 
631 #ifdef DD_DEBUG
632 #if 0
633  (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
634 #endif
635  count = 0;
636  idcheck = 0;
637  for (i = 0; i < yslots; i++) {
638  f = ylist[i];
639  while (f != sentinel) {
640  count++;
641  if (f->index != (DdHalfWord) yindex)
642  idcheck++;
643  f = f->next;
644  }
645  }
646  if (count != newykeys) {
647  fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
648  }
649  if (idcheck != 0)
650  fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
651  count = 0;
652  idcheck = 0;
653  for (i = 0; i < xslots; i++) {
654  f = xlist[i];
655  while (f != sentinel) {
656  count++;
657  if (f->index != (DdHalfWord) xindex)
658  idcheck++;
659  f = f->next;
660  }
661  }
662  if (count != newxkeys || newxkeys != oldxkeys) {
663  fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
664  }
665  if (idcheck != 0)
666  fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
667 #endif
668 
669  isolated += (table->vars[xindex]->ref == 1) +
670  (table->vars[yindex]->ref == 1);
671  table->isolated += isolated;
672 
673  /* Set the appropriate fields in table. */
674  table->subtables[y].keys = newykeys;
675 
676  /* Here we should update the linear combination table
677  ** to record that x <- x EXNOR y. This is done by complementing
678  ** the (x,y) entry of the table.
679  */
680 
681  table->keys += newykeys - oldykeys;
682 
683  cuddXorLinear(table,xindex,yindex);
684  }
685 
686 #ifdef DD_DEBUG
687  if (zero) {
688  (void) Cudd_DebugCheck(table);
689  }
690 #endif
691 
692  return(table->keys - table->isolated);
693 
694 cuddLinearOutOfMem:
695  (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
696 
697  return (0);
698 
699 } /* end of cuddLinearInPlace */
700 
701 
713 void
715  DdManager * table,
716  int xindex,
717  int yindex)
718 {
719  int i;
720  for (i = 0; i < yindex; i++) {
721  if (i != xindex && cuddTestInteract(table,i,yindex)) {
722  if (i < xindex) {
723  cuddSetInteract(table,i,xindex);
724  } else {
725  cuddSetInteract(table,xindex,i);
726  }
727  }
728  }
729  for (i = yindex+1; i < table->size; i++) {
730  if (i != xindex && cuddTestInteract(table,yindex,i)) {
731  if (i < xindex) {
732  cuddSetInteract(table,i,xindex);
733  } else {
734  cuddSetInteract(table,xindex,i);
735  }
736  }
737  }
738 
739 } /* end of cuddUpdateInteractionMatrix */
740 
741 
754 int
756  DdManager * table)
757 {
758  int words;
759  int wordsPerRow;
760  int nvars;
761  int word;
762  int bit;
763  int i;
764  long *linear;
765 
766  nvars = table->size;
767  wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
768  words = wordsPerRow * nvars;
769  table->linear = linear = ALLOC(long,words);
770  if (linear == NULL) {
771  table->errorCode = CUDD_MEMORY_OUT;
772  return(0);
773  }
774  table->memused += words * sizeof(long);
775  table->linearSize = nvars;
776  for (i = 0; i < words; i++) linear[i] = 0;
777  for (i = 0; i < nvars; i++) {
778  word = wordsPerRow * i + (i >> LOGBPL);
779  bit = i & (BPL-1);
780  linear[word] = 1 << bit;
781  }
782  return(1);
783 
784 } /* end of cuddInitLinear */
785 
786 
799 int
801  DdManager * table)
802 {
803  int words,oldWords;
804  int wordsPerRow,oldWordsPerRow;
805  int nvars,oldNvars;
806  int word,oldWord;
807  int bit;
808  int i,j;
809  long *linear,*oldLinear;
810 
811  oldNvars = table->linearSize;
812  oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
813  oldWords = oldWordsPerRow * oldNvars;
814  oldLinear = table->linear;
815 
816  nvars = table->size;
817  wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
818  words = wordsPerRow * nvars;
819  table->linear = linear = ALLOC(long,words);
820  if (linear == NULL) {
821  table->errorCode = CUDD_MEMORY_OUT;
822  return(0);
823  }
824  table->memused += (words - oldWords) * sizeof(long);
825  for (i = 0; i < words; i++) linear[i] = 0;
826 
827  /* Copy old matrix. */
828  for (i = 0; i < oldNvars; i++) {
829  for (j = 0; j < oldWordsPerRow; j++) {
830  oldWord = oldWordsPerRow * i + j;
831  word = wordsPerRow * i + j;
832  linear[word] = oldLinear[oldWord];
833  }
834  }
835  FREE(oldLinear);
836 
837  /* Add elements to the diagonal. */
838  for (i = oldNvars; i < nvars; i++) {
839  word = wordsPerRow * i + (i >> LOGBPL);
840  bit = i & (BPL-1);
841  linear[word] = 1 << bit;
842  }
843  table->linearSize = nvars;
844 
845  return(1);
846 
847 } /* end of cuddResizeLinear */
848 
849 
850 /*---------------------------------------------------------------------------*/
851 /* Definition of static functions */
852 /*---------------------------------------------------------------------------*/
853 
854 
867 static int
869  int * ptrX,
870  int * ptrY)
871 {
872 #if 0
873  if (entry[*ptrY] == entry[*ptrX]) {
874  return((*ptrX) - (*ptrY));
875  }
876 #endif
877  return(entry[*ptrY] - entry[*ptrX]);
878 
879 } /* end of ddLinearUniqueCompare */
880 
881 
895 static int
897  DdManager * table,
898  int x,
899  int xLow,
900  int xHigh)
901 {
902 
903  Move *move;
904  Move *moveUp; /* list of up moves */
905  Move *moveDown; /* list of down moves */
906  int initialSize;
907  int result;
908 
909  initialSize = table->keys - table->isolated;
910 
911  moveDown = NULL;
912  moveUp = NULL;
913 
914  if (x == xLow) {
915  moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
916  /* At this point x --> xHigh unless bounding occurred. */
917  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
918  /* Move backward and stop at best position. */
919  result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
920  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
921 
922  } else if (x == xHigh) {
923  moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
924  /* At this point x --> xLow unless bounding occurred. */
925  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
926  /* Move backward and stop at best position. */
927  result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
928  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
929 
930  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
931  moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
932  /* At this point x --> xHigh unless bounding occurred. */
933  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
934  moveUp = ddUndoMoves(table,moveDown);
935 #ifdef DD_DEBUG
936  assert(moveUp == NULL || moveUp->x == x);
937 #endif
938  moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
939  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
940  /* Move backward and stop at best position. */
941  result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
942  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
943 
944  } else { /* must go up first: shorter */
945  moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
946  /* At this point x --> xLow unless bounding occurred. */
947  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
948  moveDown = ddUndoMoves(table,moveUp);
949 #ifdef DD_DEBUG
950  assert(moveDown == NULL || moveDown->y == x);
951 #endif
952  moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
953  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
954  /* Move backward and stop at best position. */
955  result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
956  if (!result) goto ddLinearAndSiftingAuxOutOfMem;
957  }
958 
959  while (moveDown != NULL) {
960  move = moveDown->next;
961  cuddDeallocMove(table, moveDown);
962  moveDown = move;
963  }
964  while (moveUp != NULL) {
965  move = moveUp->next;
966  cuddDeallocMove(table, moveUp);
967  moveUp = move;
968  }
969 
970  return(1);
971 
972 ddLinearAndSiftingAuxOutOfMem:
973  while (moveDown != NULL) {
974  move = moveDown->next;
975  cuddDeallocMove(table, moveDown);
976  moveDown = move;
977  }
978  while (moveUp != NULL) {
979  move = moveUp->next;
980  cuddDeallocMove(table, moveUp);
981  moveUp = move;
982  }
983 
984  return(0);
985 
986 } /* end of ddLinearAndSiftingAux */
987 
988 
1001 static Move *
1003  DdManager * table,
1004  int y,
1005  int xLow,
1006  Move * prevMoves)
1007 {
1008  Move *moves;
1009  Move *move;
1010  int x;
1011  int size, newsize;
1012  int limitSize;
1013  int xindex, yindex;
1014  int isolated;
1015  int L; /* lower bound on DD size */
1016 #ifdef DD_DEBUG
1017  int checkL;
1018  int z;
1019  int zindex;
1020 #endif
1021 
1022  moves = prevMoves;
1023  yindex = table->invperm[y];
1024 
1025  /* Initialize the lower bound.
1026  ** The part of the DD below y will not change.
1027  ** The part of the DD above y that does not interact with y will not
1028  ** change. The rest may vanish in the best case, except for
1029  ** the nodes at level xLow, which will not vanish, regardless.
1030  */
1031  limitSize = L = table->keys - table->isolated;
1032  for (x = xLow + 1; x < y; x++) {
1033  xindex = table->invperm[x];
1034  if (cuddTestInteract(table,xindex,yindex)) {
1035  isolated = table->vars[xindex]->ref == 1;
1036  L -= table->subtables[x].keys - isolated;
1037  }
1038  }
1039  isolated = table->vars[yindex]->ref == 1;
1040  L -= table->subtables[y].keys - isolated;
1041 
1042  x = cuddNextLow(table,y);
1043  while (x >= xLow && L <= limitSize) {
1044  xindex = table->invperm[x];
1045 #ifdef DD_DEBUG
1046  checkL = table->keys - table->isolated;
1047  for (z = xLow + 1; z < y; z++) {
1048  zindex = table->invperm[z];
1049  if (cuddTestInteract(table,zindex,yindex)) {
1050  isolated = table->vars[zindex]->ref == 1;
1051  checkL -= table->subtables[z].keys - isolated;
1052  }
1053  }
1054  isolated = table->vars[yindex]->ref == 1;
1055  checkL -= table->subtables[y].keys - isolated;
1056  if (L != checkL) {
1057  (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
1058  }
1059 #endif
1060  size = cuddSwapInPlace(table,x,y);
1061  if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
1062  newsize = cuddLinearInPlace(table,x,y);
1063  if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
1064  move = (Move *) cuddDynamicAllocNode(table);
1065  if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
1066  move->x = x;
1067  move->y = y;
1068  move->next = moves;
1069  moves = move;
1070  move->flags = CUDD_SWAP_MOVE;
1071  if (newsize >= size) {
1072  /* Undo transformation. The transformation we apply is
1073  ** its own inverse. Hence, we just apply the transformation
1074  ** again.
1075  */
1076  newsize = cuddLinearInPlace(table,x,y);
1077  if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
1078 #ifdef DD_DEBUG
1079  if (newsize != size) {
1080  (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
1081  }
1082 #endif
1083  } else if (cuddTestInteract(table,xindex,yindex)) {
1084  size = newsize;
1086  cuddUpdateInteractionMatrix(table,xindex,yindex);
1087  }
1088  move->size = size;
1089  /* Update the lower bound. */
1090  if (cuddTestInteract(table,xindex,yindex)) {
1091  isolated = table->vars[xindex]->ref == 1;
1092  L += table->subtables[y].keys - isolated;
1093  }
1094  if ((double) size > (double) limitSize * table->maxGrowth) break;
1095  if (size < limitSize) limitSize = size;
1096  y = x;
1097  x = cuddNextLow(table,y);
1098  }
1099  return(moves);
1100 
1101 ddLinearAndSiftingUpOutOfMem:
1102  while (moves != NULL) {
1103  move = moves->next;
1104  cuddDeallocMove(table, moves);
1105  moves = move;
1106  }
1107  return((Move *) CUDD_OUT_OF_MEM);
1108 
1109 } /* end of ddLinearAndSiftingUp */
1110 
1111 
1124 static Move *
1126  DdManager * table,
1127  int x,
1128  int xHigh,
1129  Move * prevMoves)
1130 {
1131  Move *moves;
1132  Move *move;
1133  int y;
1134  int size, newsize;
1135  int R; /* upper bound on node decrease */
1136  int limitSize;
1137  int xindex, yindex;
1138  int isolated;
1139 #ifdef DD_DEBUG
1140  int checkR;
1141  int z;
1142  int zindex;
1143 #endif
1144 
1145  moves = prevMoves;
1146  /* Initialize R */
1147  xindex = table->invperm[x];
1148  limitSize = size = table->keys - table->isolated;
1149  R = 0;
1150  for (y = xHigh; y > x; y--) {
1151  yindex = table->invperm[y];
1152  if (cuddTestInteract(table,xindex,yindex)) {
1153  isolated = table->vars[yindex]->ref == 1;
1154  R += table->subtables[y].keys - isolated;
1155  }
1156  }
1157 
1158  y = cuddNextHigh(table,x);
1159  while (y <= xHigh && size - R < limitSize) {
1160 #ifdef DD_DEBUG
1161  checkR = 0;
1162  for (z = xHigh; z > x; z--) {
1163  zindex = table->invperm[z];
1164  if (cuddTestInteract(table,xindex,zindex)) {
1165  isolated = table->vars[zindex]->ref == 1;
1166  checkR += table->subtables[z].keys - isolated;
1167  }
1168  }
1169  if (R != checkR) {
1170  (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
1171  }
1172 #endif
1173  /* Update upper bound on node decrease. */
1174  yindex = table->invperm[y];
1175  if (cuddTestInteract(table,xindex,yindex)) {
1176  isolated = table->vars[yindex]->ref == 1;
1177  R -= table->subtables[y].keys - isolated;
1178  }
1179  size = cuddSwapInPlace(table,x,y);
1180  if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
1181  newsize = cuddLinearInPlace(table,x,y);
1182  if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
1183  move = (Move *) cuddDynamicAllocNode(table);
1184  if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
1185  move->x = x;
1186  move->y = y;
1187  move->next = moves;
1188  moves = move;
1189  move->flags = CUDD_SWAP_MOVE;
1190  if (newsize >= size) {
1191  /* Undo transformation. The transformation we apply is
1192  ** its own inverse. Hence, we just apply the transformation
1193  ** again.
1194  */
1195  newsize = cuddLinearInPlace(table,x,y);
1196  if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
1197  if (newsize != size) {
1198  (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
1199  }
1200  } else if (cuddTestInteract(table,xindex,yindex)) {
1201  size = newsize;
1203  cuddUpdateInteractionMatrix(table,xindex,yindex);
1204  }
1205  move->size = size;
1206  if ((double) size > (double) limitSize * table->maxGrowth) break;
1207  if (size < limitSize) limitSize = size;
1208  x = y;
1209  y = cuddNextHigh(table,x);
1210  }
1211  return(moves);
1212 
1213 ddLinearAndSiftingDownOutOfMem:
1214  while (moves != NULL) {
1215  move = moves->next;
1216  cuddDeallocMove(table, moves);
1217  moves = move;
1218  }
1219  return((Move *) CUDD_OUT_OF_MEM);
1220 
1221 } /* end of ddLinearAndSiftingDown */
1222 
1223 
1237 static int
1239  DdManager * table,
1240  int size,
1241  Move * moves)
1242 {
1243  Move *move;
1244  int res;
1245 
1246  for (move = moves; move != NULL; move = move->next) {
1247  if (move->size < size) {
1248  size = move->size;
1249  }
1250  }
1251 
1252  for (move = moves; move != NULL; move = move->next) {
1253  if (move->size == size) return(1);
1254  if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
1255  res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
1256  if (!res) return(0);
1257  }
1258  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1259  if (!res) return(0);
1260  if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
1261  res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
1262  if (!res) return(0);
1263  }
1264  }
1265 
1266  return(1);
1267 
1268 } /* end of ddLinearAndSiftingBackward */
1269 
1270 
1283 static Move*
1285  DdManager * table,
1286  Move * moves)
1287 {
1288  Move *invmoves = NULL;
1289  Move *move;
1290  Move *invmove;
1291  int size;
1292 
1293  for (move = moves; move != NULL; move = move->next) {
1294  invmove = (Move *) cuddDynamicAllocNode(table);
1295  if (invmove == NULL) goto ddUndoMovesOutOfMem;
1296  invmove->x = move->x;
1297  invmove->y = move->y;
1298  invmove->next = invmoves;
1299  invmoves = invmove;
1300  if (move->flags == CUDD_SWAP_MOVE) {
1301  invmove->flags = CUDD_SWAP_MOVE;
1302  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1303  if (!size) goto ddUndoMovesOutOfMem;
1304  } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
1306  size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
1307  if (!size) goto ddUndoMovesOutOfMem;
1308  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1309  if (!size) goto ddUndoMovesOutOfMem;
1310  } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
1311 #ifdef DD_DEBUG
1312  (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
1313 #endif
1314  invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
1315  size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1316  if (!size) goto ddUndoMovesOutOfMem;
1317  size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
1318  if (!size) goto ddUndoMovesOutOfMem;
1319  }
1320  invmove->size = size;
1321  }
1322 
1323  return(invmoves);
1324 
1325 ddUndoMovesOutOfMem:
1326  while (invmoves != NULL) {
1327  move = invmoves->next;
1328  cuddDeallocMove(table, invmoves);
1329  invmoves = move;
1330  }
1331  return((Move *) CUDD_OUT_OF_MEM);
1332 
1333 } /* end of ddUndoMoves */
1334 
1335 
1348 static void
1350  DdManager * table,
1351  int x,
1352  int y)
1353 {
1354  int i;
1355  int nvars = table->size;
1356  int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
1357  int xstart = wordsPerRow * x;
1358  int ystart = wordsPerRow * y;
1359  long *linear = table->linear;
1360 
1361  for (i = 0; i < wordsPerRow; i++) {
1362  linear[xstart+i] ^= linear[ystart+i];
1363  }
1364 
1365 } /* end of cuddXorLinear */
static char rcsid [] DD_UNUSED
Definition: cuddLinear.c:95
DdHalfWord ref
Definition: cudd.h:272
unsigned int keys
Definition: cuddInt.h:314
#define CUDD_OUT_OF_MEM
Definition: cudd.h:91
unsigned short DdHalfWord
Definition: cudd.h:259
#define ddHash(f, g, s)
Definition: cuddInt.h:696
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
Definition: cudd.h:270
#define Cudd_Not(node)
Definition: cudd.h:354
#define FREE(obj)
Definition: util.h:80
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
static void cuddXorLinear(DdManager *table, int x, int y)
Definition: cuddLinear.c:1349
#define assert(ex)
Definition: util.h:141
#define BPL
Definition: cuddLinear.c:78
int size
Definition: cuddInt.h:345
Definition: cuddInt.h:469
void cuddSetInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:153
#define Cudd_Regular(node)
Definition: cudd.h:384
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:737
#define CUDD_INVERSE_TRANSFORM_MOVE
Definition: cuddLinear.c:73
int cuddInitLinear(DdManager *table)
Definition: cuddLinear.c:755
double maxGrowth
Definition: cuddInt.h:397
FILE * err
Definition: cuddInt.h:424
static int ddLinearAndSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddLinear.c:1238
#define LOGBPL
Definition: cuddLinear.c:79
DdSubtable * subtables
Definition: cuddInt.h:349
int Cudd_ReadLinear(DdManager *table, int x, int y)
Definition: cuddLinear.c:187
int cuddResizeLinear(DdManager *table)
Definition: cuddLinear.c:800
int ddTotalNumberSwapping
Definition: cuddReorder.c:103
#define Cudd_IsComplement(node)
Definition: cudd.h:412
int Cudd_PrintLinear(DdManager *table)
Definition: cuddLinear.c:149
DdNode sentinel
Definition: cuddInt.h:328
unsigned int keys
Definition: cuddInt.h:353
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
static Move * ddUndoMoves(DdManager *table, Move *moves)
Definition: cuddLinear.c:1284
FILE * out
Definition: cuddInt.h:423
unsigned int flags
Definition: cuddInt.h:472
DdHalfWord x
Definition: cuddInt.h:470
DdNode * next
Definition: cudd.h:273
#define CUDD_SWAP_MOVE
Definition: cuddLinear.c:71
#define CUDD_LINEAR_TRANSFORM_MOVE
Definition: cuddLinear.c:72
long * linear
Definition: cuddInt.h:378
DdNode ** nodelist
Definition: cuddInt.h:311
int cuddLinearAndSifting(DdManager *table, int lower, int upper)
Definition: cuddLinear.c:236
int Cudd_DebugCheck(DdManager *table)
Definition: cuddCheck.c:138
int linearSize
Definition: cuddInt.h:376
void cuddUpdateInteractionMatrix(DdManager *table, int xindex, int yindex)
Definition: cuddLinear.c:714
#define ddMin(x, y)
Definition: cuddInt.h:771
int cuddLinearInPlace(DdManager *table, int x, int y)
Definition: cuddLinear.c:360
#define cuddT(node)
Definition: cuddInt.h:609
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:715
static Move * ddLinearAndSiftingUp(DdManager *table, int y, int xLow, Move *prevMoves)
Definition: cuddLinear.c:1002
unsigned long memused
Definition: cuddInt.h:429
int siftMaxVar
Definition: cuddInt.h:395
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:760
static int * entry
Definition: cuddLinear.c:98
DdHalfWord index
Definition: cudd.h:271
unsigned int slots
Definition: cuddInt.h:313
DdHalfWord y
Definition: cuddInt.h:471
DdNode ** vars
Definition: cuddInt.h:373
static DdNode * zero
Definition: cuddSat.c:105
#define cuddE(node)
Definition: cuddInt.h:625
struct Move * next
Definition: cuddInt.h:474
static int ddLinearUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddLinear.c:868
static Move * ddLinearAndSiftingDown(DdManager *table, int x, int xHigh, Move *prevMoves)
Definition: cuddLinear.c:1125
#define cuddSatDec(x)
Definition: cuddInt.h:849
int * invperm
Definition: cuddInt.h:371
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:188
int shift
Definition: cuddInt.h:312
int * perm
Definition: cuddInt.h:369
int size
Definition: cuddInt.h:473
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
#define cuddSatInc(x)
Definition: cuddInt.h:831
static int ddLinearAndSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddLinear.c:896