#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | CUDD_SWAP_MOVE 0 |
#define | CUDD_LINEAR_TRANSFORM_MOVE 1 |
#define | CUDD_INVERSE_TRANSFORM_MOVE 2 |
#define | BPL 32 |
#define | LOGBPL 5 |
Functions | |
static int | ddLinearUniqueCompare (int *ptrX, int *ptrY) |
static int | ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh) |
static Move * | ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves) |
static Move * | ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves) |
static int | ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves) |
static Move * | ddUndoMoves (DdManager *table, Move *moves) |
static void | cuddXorLinear (DdManager *table, int x, int y) |
int | Cudd_PrintLinear (DdManager *table) |
int | Cudd_ReadLinear (DdManager *table, int x, int y) |
int | cuddLinearAndSifting (DdManager *table, int lower, int upper) |
int | cuddLinearInPlace (DdManager *table, int x, int y) |
void | cuddUpdateInteractionMatrix (DdManager *table, int xindex, int yindex) |
int | cuddInitLinear (DdManager *table) |
int | cuddResizeLinear (DdManager *table) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $" |
static int * | entry |
#define BPL 32 |
Definition at line 78 of file cuddLinear.c.
#define CUDD_INVERSE_TRANSFORM_MOVE 2 |
Definition at line 73 of file cuddLinear.c.
#define CUDD_LINEAR_TRANSFORM_MOVE 1 |
Definition at line 72 of file cuddLinear.c.
#define CUDD_SWAP_MOVE 0 |
CFile***********************************************************************
FileName [cuddLinear.c]
PackageName [cudd]
Synopsis [Functions for DD reduction by linear transformations.]
Description [ Internal procedures included in this module:
Static procedures included in this module:
]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
Definition at line 71 of file cuddLinear.c.
#define LOGBPL 5 |
Definition at line 79 of file cuddLinear.c.
int Cudd_PrintLinear | ( | DdManager * | table | ) |
AutomaticEnd Function********************************************************************
Synopsis [Prints the linear transform matrix.]
Description [Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 149 of file cuddLinear.c.
00151 { 00152 int i,j,k; 00153 int retval; 00154 int nvars = table->linearSize; 00155 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00156 long word; 00157 00158 for (i = 0; i < nvars; i++) { 00159 for (j = 0; j < wordsPerRow; j++) { 00160 word = table->linear[i*wordsPerRow + j]; 00161 for (k = 0; k < BPL; k++) { 00162 retval = fprintf(table->out,"%ld",word & 1); 00163 if (retval == 0) return(0); 00164 word >>= 1; 00165 } 00166 } 00167 retval = fprintf(table->out,"\n"); 00168 if (retval == 0) return(0); 00169 } 00170 return(1); 00171 00172 } /* end of Cudd_PrintLinear */
int Cudd_ReadLinear | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Reads an entry of the linear transform matrix.]
Description [Reads an entry of the linear transform matrix.]
SideEffects [none]
SeeAlso []
Definition at line 187 of file cuddLinear.c.
00191 { 00192 int nvars = table->size; 00193 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00194 long word; 00195 int bit; 00196 int result; 00197 00198 assert(table->size == table->linearSize); 00199 00200 word = wordsPerRow * x + (y >> LOGBPL); 00201 bit = y & (BPL-1); 00202 result = (int) ((table->linear[word] >> bit) & 1); 00203 return(result); 00204 00205 } /* end of Cudd_ReadLinear */
int cuddInitLinear | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Initializes the linear transform matrix.]
Description [Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 755 of file cuddLinear.c.
00757 { 00758 int words; 00759 int wordsPerRow; 00760 int nvars; 00761 int word; 00762 int bit; 00763 int i; 00764 long *linear; 00765 00766 nvars = table->size; 00767 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00768 words = wordsPerRow * nvars; 00769 table->linear = linear = ALLOC(long,words); 00770 if (linear == NULL) { 00771 table->errorCode = CUDD_MEMORY_OUT; 00772 return(0); 00773 } 00774 table->memused += words * sizeof(long); 00775 table->linearSize = nvars; 00776 for (i = 0; i < words; i++) linear[i] = 0; 00777 for (i = 0; i < nvars; i++) { 00778 word = wordsPerRow * i + (i >> LOGBPL); 00779 bit = i & (BPL-1); 00780 linear[word] = 1 << bit; 00781 } 00782 return(1); 00783 00784 } /* end of cuddInitLinear */
int cuddLinearAndSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [BDD reduction based on combination of sifting and linear transformations.]
Description [BDD reduction based on combination of sifting and linear transformations. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 236 of file cuddLinear.c.
00240 { 00241 int i; 00242 int *var; 00243 int size; 00244 int x; 00245 int result; 00246 #ifdef DD_STATS 00247 int previousSize; 00248 #endif 00249 00250 #ifdef DD_STATS 00251 ddTotalNumberLinearTr = 0; 00252 #endif 00253 00254 size = table->size; 00255 00256 var = NULL; 00257 entry = NULL; 00258 if (table->linear == NULL) { 00259 result = cuddInitLinear(table); 00260 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00261 #if 0 00262 (void) fprintf(table->out,"\n"); 00263 result = Cudd_PrintLinear(table); 00264 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00265 #endif 00266 } else if (table->size != table->linearSize) { 00267 result = cuddResizeLinear(table); 00268 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00269 #if 0 00270 (void) fprintf(table->out,"\n"); 00271 result = Cudd_PrintLinear(table); 00272 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00273 #endif 00274 } 00275 00276 /* Find order in which to sift variables. */ 00277 entry = ALLOC(int,size); 00278 if (entry == NULL) { 00279 table->errorCode = CUDD_MEMORY_OUT; 00280 goto cuddLinearAndSiftingOutOfMem; 00281 } 00282 var = ALLOC(int,size); 00283 if (var == NULL) { 00284 table->errorCode = CUDD_MEMORY_OUT; 00285 goto cuddLinearAndSiftingOutOfMem; 00286 } 00287 00288 for (i = 0; i < size; i++) { 00289 x = table->perm[i]; 00290 entry[i] = table->subtables[x].keys; 00291 var[i] = i; 00292 } 00293 00294 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare); 00295 00296 /* Now sift. */ 00297 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00298 x = table->perm[var[i]]; 00299 if (x < lower || x > upper) continue; 00300 #ifdef DD_STATS 00301 previousSize = table->keys - table->isolated; 00302 #endif 00303 result = ddLinearAndSiftingAux(table,x,lower,upper); 00304 if (!result) goto cuddLinearAndSiftingOutOfMem; 00305 #ifdef DD_STATS 00306 if (table->keys < (unsigned) previousSize + table->isolated) { 00307 (void) fprintf(table->out,"-"); 00308 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00309 (void) fprintf(table->out,"+"); /* should never happen */ 00310 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); 00311 } else { 00312 (void) fprintf(table->out,"="); 00313 } 00314 fflush(table->out); 00315 #endif 00316 #ifdef DD_DEBUG 00317 (void) Cudd_DebugCheck(table); 00318 #endif 00319 } 00320 00321 FREE(var); 00322 FREE(entry); 00323 00324 #ifdef DD_STATS 00325 (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", 00326 ddTotalNumberLinearTr); 00327 #endif 00328 00329 return(1); 00330 00331 cuddLinearAndSiftingOutOfMem: 00332 00333 if (entry != NULL) FREE(entry); 00334 if (var != NULL) FREE(var); 00335 00336 return(0); 00337 00338 } /* end of cuddLinearAndSifting */
int cuddLinearInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Linearly combines two adjacent variables.]
Description [Linearly combines two adjacent variables. Specifically, replaces the top variable with the exclusive nor of the two variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [The two subtables corrresponding to variables x and y are modified. The global counters of the unique table are also affected.]
SeeAlso [cuddSwapInPlace]
Definition at line 360 of file cuddLinear.c.
00364 { 00365 DdNodePtr *xlist, *ylist; 00366 int xindex, yindex; 00367 int xslots, yslots; 00368 int xshift, yshift; 00369 int oldxkeys, oldykeys; 00370 int newxkeys, newykeys; 00371 int comple, newcomplement; 00372 int i; 00373 int posn; 00374 int isolated; 00375 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; 00376 DdNode *g,*next,*last; 00377 DdNodePtr *previousP; 00378 DdNode *tmp; 00379 DdNode *sentinel = &(table->sentinel); 00380 #ifdef DD_DEBUG 00381 int count, idcheck; 00382 #endif 00383 00384 #ifdef DD_DEBUG 00385 assert(x < y); 00386 assert(cuddNextHigh(table,x) == y); 00387 assert(table->subtables[x].keys != 0); 00388 assert(table->subtables[y].keys != 0); 00389 assert(table->subtables[x].dead == 0); 00390 assert(table->subtables[y].dead == 0); 00391 #endif 00392 00393 xindex = table->invperm[x]; 00394 yindex = table->invperm[y]; 00395 00396 if (cuddTestInteract(table,xindex,yindex)) { 00397 #ifdef DD_STATS 00398 ddTotalNumberLinearTr++; 00399 #endif 00400 /* Get parameters of x subtable. */ 00401 xlist = table->subtables[x].nodelist; 00402 oldxkeys = table->subtables[x].keys; 00403 xslots = table->subtables[x].slots; 00404 xshift = table->subtables[x].shift; 00405 00406 /* Get parameters of y subtable. */ 00407 ylist = table->subtables[y].nodelist; 00408 oldykeys = table->subtables[y].keys; 00409 yslots = table->subtables[y].slots; 00410 yshift = table->subtables[y].shift; 00411 00412 newxkeys = 0; 00413 newykeys = oldykeys; 00414 00415 /* Check whether the two projection functions involved in this 00416 ** swap are isolated. At the end, we'll be able to tell how many 00417 ** isolated projection functions are there by checking only these 00418 ** two functions again. This is done to eliminate the isolated 00419 ** projection functions from the node count. 00420 */ 00421 isolated = - ((table->vars[xindex]->ref == 1) + 00422 (table->vars[yindex]->ref == 1)); 00423 00424 /* The nodes in the x layer are put in a chain. 00425 ** The chain is handled as a FIFO; g points to the beginning and 00426 ** last points to the end. 00427 */ 00428 g = NULL; 00429 #ifdef DD_DEBUG 00430 last = NULL; 00431 #endif 00432 for (i = 0; i < xslots; i++) { 00433 f = xlist[i]; 00434 if (f == sentinel) continue; 00435 xlist[i] = sentinel; 00436 if (g == NULL) { 00437 g = f; 00438 } else { 00439 last->next = f; 00440 } 00441 while ((next = f->next) != sentinel) { 00442 f = next; 00443 } /* while there are elements in the collision chain */ 00444 last = f; 00445 } /* for each slot of the x subtable */ 00446 #ifdef DD_DEBUG 00447 /* last is always assigned in the for loop because there is at 00448 ** least one key */ 00449 assert(last != NULL); 00450 #endif 00451 last->next = NULL; 00452 00453 #ifdef DD_COUNT 00454 table->swapSteps += oldxkeys; 00455 #endif 00456 /* Take care of the x nodes that must be re-expressed. 00457 ** They form a linked list pointed by g. 00458 */ 00459 f = g; 00460 while (f != NULL) { 00461 next = f->next; 00462 /* Find f1, f0, f11, f10, f01, f00. */ 00463 f1 = cuddT(f); 00464 #ifdef DD_DEBUG 00465 assert(!(Cudd_IsComplement(f1))); 00466 #endif 00467 if ((int) f1->index == yindex) { 00468 f11 = cuddT(f1); f10 = cuddE(f1); 00469 } else { 00470 f11 = f10 = f1; 00471 } 00472 #ifdef DD_DEBUG 00473 assert(!(Cudd_IsComplement(f11))); 00474 #endif 00475 f0 = cuddE(f); 00476 comple = Cudd_IsComplement(f0); 00477 f0 = Cudd_Regular(f0); 00478 if ((int) f0->index == yindex) { 00479 f01 = cuddT(f0); f00 = cuddE(f0); 00480 } else { 00481 f01 = f00 = f0; 00482 } 00483 if (comple) { 00484 f01 = Cudd_Not(f01); 00485 f00 = Cudd_Not(f00); 00486 } 00487 /* Decrease ref count of f1. */ 00488 cuddSatDec(f1->ref); 00489 /* Create the new T child. */ 00490 if (f11 == f00) { 00491 newf1 = f11; 00492 cuddSatInc(newf1->ref); 00493 } else { 00494 /* Check ylist for triple (yindex,f11,f00). */ 00495 posn = ddHash(f11, f00, yshift); 00496 /* For each element newf1 in collision list ylist[posn]. */ 00497 previousP = &(ylist[posn]); 00498 newf1 = *previousP; 00499 while (f11 < cuddT(newf1)) { 00500 previousP = &(newf1->next); 00501 newf1 = *previousP; 00502 } 00503 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { 00504 previousP = &(newf1->next); 00505 newf1 = *previousP; 00506 } 00507 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { 00508 cuddSatInc(newf1->ref); 00509 } else { /* no match */ 00510 newf1 = cuddDynamicAllocNode(table); 00511 if (newf1 == NULL) 00512 goto cuddLinearOutOfMem; 00513 newf1->index = yindex; newf1->ref = 1; 00514 cuddT(newf1) = f11; 00515 cuddE(newf1) = f00; 00516 /* Insert newf1 in the collision list ylist[posn]; 00517 ** increase the ref counts of f11 and f00. 00518 */ 00519 newykeys++; 00520 newf1->next = *previousP; 00521 *previousP = newf1; 00522 cuddSatInc(f11->ref); 00523 tmp = Cudd_Regular(f00); 00524 cuddSatInc(tmp->ref); 00525 } 00526 } 00527 cuddT(f) = newf1; 00528 #ifdef DD_DEBUG 00529 assert(!(Cudd_IsComplement(newf1))); 00530 #endif 00531 00532 /* Do the same for f0, keeping complement dots into account. */ 00533 /* decrease ref count of f0 */ 00534 tmp = Cudd_Regular(f0); 00535 cuddSatDec(tmp->ref); 00536 /* create the new E child */ 00537 if (f01 == f10) { 00538 newf0 = f01; 00539 tmp = Cudd_Regular(newf0); 00540 cuddSatInc(tmp->ref); 00541 } else { 00542 /* make sure f01 is regular */ 00543 newcomplement = Cudd_IsComplement(f01); 00544 if (newcomplement) { 00545 f01 = Cudd_Not(f01); 00546 f10 = Cudd_Not(f10); 00547 } 00548 /* Check ylist for triple (yindex,f01,f10). */ 00549 posn = ddHash(f01, f10, yshift); 00550 /* For each element newf0 in collision list ylist[posn]. */ 00551 previousP = &(ylist[posn]); 00552 newf0 = *previousP; 00553 while (f01 < cuddT(newf0)) { 00554 previousP = &(newf0->next); 00555 newf0 = *previousP; 00556 } 00557 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { 00558 previousP = &(newf0->next); 00559 newf0 = *previousP; 00560 } 00561 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { 00562 cuddSatInc(newf0->ref); 00563 } else { /* no match */ 00564 newf0 = cuddDynamicAllocNode(table); 00565 if (newf0 == NULL) 00566 goto cuddLinearOutOfMem; 00567 newf0->index = yindex; newf0->ref = 1; 00568 cuddT(newf0) = f01; 00569 cuddE(newf0) = f10; 00570 /* Insert newf0 in the collision list ylist[posn]; 00571 ** increase the ref counts of f01 and f10. 00572 */ 00573 newykeys++; 00574 newf0->next = *previousP; 00575 *previousP = newf0; 00576 cuddSatInc(f01->ref); 00577 tmp = Cudd_Regular(f10); 00578 cuddSatInc(tmp->ref); 00579 } 00580 if (newcomplement) { 00581 newf0 = Cudd_Not(newf0); 00582 } 00583 } 00584 cuddE(f) = newf0; 00585 00586 /* Re-insert the modified f in xlist. 00587 ** The modified f does not already exists in xlist. 00588 ** (Because of the uniqueness of the cofactors.) 00589 */ 00590 posn = ddHash(newf1, newf0, xshift); 00591 newxkeys++; 00592 previousP = &(xlist[posn]); 00593 tmp = *previousP; 00594 while (newf1 < cuddT(tmp)) { 00595 previousP = &(tmp->next); 00596 tmp = *previousP; 00597 } 00598 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { 00599 previousP = &(tmp->next); 00600 tmp = *previousP; 00601 } 00602 f->next = *previousP; 00603 *previousP = f; 00604 f = next; 00605 } /* while f != NULL */ 00606 00607 /* GC the y layer. */ 00608 00609 /* For each node f in ylist. */ 00610 for (i = 0; i < yslots; i++) { 00611 previousP = &(ylist[i]); 00612 f = *previousP; 00613 while (f != sentinel) { 00614 next = f->next; 00615 if (f->ref == 0) { 00616 tmp = cuddT(f); 00617 cuddSatDec(tmp->ref); 00618 tmp = Cudd_Regular(cuddE(f)); 00619 cuddSatDec(tmp->ref); 00620 cuddDeallocNode(table,f); 00621 newykeys--; 00622 } else { 00623 *previousP = f; 00624 previousP = &(f->next); 00625 } 00626 f = next; 00627 } /* while f */ 00628 *previousP = sentinel; 00629 } /* for every collision list */ 00630 00631 #ifdef DD_DEBUG 00632 #if 0 00633 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); 00634 #endif 00635 count = 0; 00636 idcheck = 0; 00637 for (i = 0; i < yslots; i++) { 00638 f = ylist[i]; 00639 while (f != sentinel) { 00640 count++; 00641 if (f->index != (DdHalfWord) yindex) 00642 idcheck++; 00643 f = f->next; 00644 } 00645 } 00646 if (count != newykeys) { 00647 fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); 00648 } 00649 if (idcheck != 0) 00650 fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); 00651 count = 0; 00652 idcheck = 0; 00653 for (i = 0; i < xslots; i++) { 00654 f = xlist[i]; 00655 while (f != sentinel) { 00656 count++; 00657 if (f->index != (DdHalfWord) xindex) 00658 idcheck++; 00659 f = f->next; 00660 } 00661 } 00662 if (count != newxkeys || newxkeys != oldxkeys) { 00663 fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); 00664 } 00665 if (idcheck != 0) 00666 fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); 00667 #endif 00668 00669 isolated += (table->vars[xindex]->ref == 1) + 00670 (table->vars[yindex]->ref == 1); 00671 table->isolated += isolated; 00672 00673 /* Set the appropriate fields in table. */ 00674 table->subtables[y].keys = newykeys; 00675 00676 /* Here we should update the linear combination table 00677 ** to record that x <- x EXNOR y. This is done by complementing 00678 ** the (x,y) entry of the table. 00679 */ 00680 00681 table->keys += newykeys - oldykeys; 00682 00683 cuddXorLinear(table,xindex,yindex); 00684 } 00685 00686 #ifdef DD_DEBUG 00687 if (zero) { 00688 (void) Cudd_DebugCheck(table); 00689 } 00690 #endif 00691 00692 return(table->keys - table->isolated); 00693 00694 cuddLinearOutOfMem: 00695 (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); 00696 00697 return (0); 00698 00699 } /* end of cuddLinearInPlace */
int cuddResizeLinear | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Resizes the linear transform matrix.]
Description [Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 800 of file cuddLinear.c.
00802 { 00803 int words,oldWords; 00804 int wordsPerRow,oldWordsPerRow; 00805 int nvars,oldNvars; 00806 int word,oldWord; 00807 int bit; 00808 int i,j; 00809 long *linear,*oldLinear; 00810 00811 oldNvars = table->linearSize; 00812 oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; 00813 oldWords = oldWordsPerRow * oldNvars; 00814 oldLinear = table->linear; 00815 00816 nvars = table->size; 00817 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00818 words = wordsPerRow * nvars; 00819 table->linear = linear = ALLOC(long,words); 00820 if (linear == NULL) { 00821 table->errorCode = CUDD_MEMORY_OUT; 00822 return(0); 00823 } 00824 table->memused += (words - oldWords) * sizeof(long); 00825 for (i = 0; i < words; i++) linear[i] = 0; 00826 00827 /* Copy old matrix. */ 00828 for (i = 0; i < oldNvars; i++) { 00829 for (j = 0; j < oldWordsPerRow; j++) { 00830 oldWord = oldWordsPerRow * i + j; 00831 word = wordsPerRow * i + j; 00832 linear[word] = oldLinear[oldWord]; 00833 } 00834 } 00835 FREE(oldLinear); 00836 00837 /* Add elements to the diagonal. */ 00838 for (i = oldNvars; i < nvars; i++) { 00839 word = wordsPerRow * i + (i >> LOGBPL); 00840 bit = i & (BPL-1); 00841 linear[word] = 1 << bit; 00842 } 00843 table->linearSize = nvars; 00844 00845 return(1); 00846 00847 } /* end of cuddResizeLinear */
void cuddUpdateInteractionMatrix | ( | DdManager * | table, | |
int | xindex, | |||
int | yindex | |||
) |
Function********************************************************************
Synopsis [Updates the interaction matrix.]
Description []
SideEffects [none]
SeeAlso []
Definition at line 714 of file cuddLinear.c.
00718 { 00719 int i; 00720 for (i = 0; i < yindex; i++) { 00721 if (i != xindex && cuddTestInteract(table,i,yindex)) { 00722 if (i < xindex) { 00723 cuddSetInteract(table,i,xindex); 00724 } else { 00725 cuddSetInteract(table,xindex,i); 00726 } 00727 } 00728 } 00729 for (i = yindex+1; i < table->size; i++) { 00730 if (i != xindex && cuddTestInteract(table,yindex,i)) { 00731 if (i < xindex) { 00732 cuddSetInteract(table,i,xindex); 00733 } else { 00734 cuddSetInteract(table,xindex,i); 00735 } 00736 } 00737 } 00738 00739 } /* end of cuddUpdateInteractionMatrix */
static void cuddXorLinear | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [XORs two rows of the linear transform matrix.]
Description [XORs two rows of the linear transform matrix and replaces the first row with the result.]
SideEffects [none]
SeeAlso []
Definition at line 1349 of file cuddLinear.c.
01353 { 01354 int i; 01355 int nvars = table->size; 01356 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 01357 int xstart = wordsPerRow * x; 01358 int ystart = wordsPerRow * y; 01359 long *linear = table->linear; 01360 01361 for (i = 0; i < wordsPerRow; i++) { 01362 linear[xstart+i] ^= linear[ystart+i]; 01363 } 01364 01365 } /* end of cuddXorLinear */
static int ddLinearAndSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh | |||
) | [static] |
Function********************************************************************
Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]
Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. At each step a linear transformation is tried, and, if it decreases the size of the DD, it is accepted. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 896 of file cuddLinear.c.
00901 { 00902 00903 Move *move; 00904 Move *moveUp; /* list of up moves */ 00905 Move *moveDown; /* list of down moves */ 00906 int initialSize; 00907 int result; 00908 00909 initialSize = table->keys - table->isolated; 00910 00911 moveDown = NULL; 00912 moveUp = NULL; 00913 00914 if (x == xLow) { 00915 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); 00916 /* At this point x --> xHigh unless bounding occurred. */ 00917 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00918 /* Move backward and stop at best position. */ 00919 result = ddLinearAndSiftingBackward(table,initialSize,moveDown); 00920 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00921 00922 } else if (x == xHigh) { 00923 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); 00924 /* At this point x --> xLow unless bounding occurred. */ 00925 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00926 /* Move backward and stop at best position. */ 00927 result = ddLinearAndSiftingBackward(table,initialSize,moveUp); 00928 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00929 00930 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ 00931 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); 00932 /* At this point x --> xHigh unless bounding occurred. */ 00933 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00934 moveUp = ddUndoMoves(table,moveDown); 00935 #ifdef DD_DEBUG 00936 assert(moveUp == NULL || moveUp->x == x); 00937 #endif 00938 moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); 00939 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00940 /* Move backward and stop at best position. */ 00941 result = ddLinearAndSiftingBackward(table,initialSize,moveUp); 00942 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00943 00944 } else { /* must go up first: shorter */ 00945 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); 00946 /* At this point x --> xLow unless bounding occurred. */ 00947 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00948 moveDown = ddUndoMoves(table,moveUp); 00949 #ifdef DD_DEBUG 00950 assert(moveDown == NULL || moveDown->y == x); 00951 #endif 00952 moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); 00953 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00954 /* Move backward and stop at best position. */ 00955 result = ddLinearAndSiftingBackward(table,initialSize,moveDown); 00956 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00957 } 00958 00959 while (moveDown != NULL) { 00960 move = moveDown->next; 00961 cuddDeallocMove(table, moveDown); 00962 moveDown = move; 00963 } 00964 while (moveUp != NULL) { 00965 move = moveUp->next; 00966 cuddDeallocMove(table, moveUp); 00967 moveUp = move; 00968 } 00969 00970 return(1); 00971 00972 ddLinearAndSiftingAuxOutOfMem: 00973 while (moveDown != NULL) { 00974 move = moveDown->next; 00975 cuddDeallocMove(table, moveDown); 00976 moveDown = move; 00977 } 00978 while (moveUp != NULL) { 00979 move = moveUp->next; 00980 cuddDeallocMove(table, moveUp); 00981 moveUp = move; 00982 } 00983 00984 return(0); 00985 00986 } /* end of ddLinearAndSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the order giving the minimum size.]
Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 1238 of file cuddLinear.c.
01242 { 01243 Move *move; 01244 int res; 01245 01246 for (move = moves; move != NULL; move = move->next) { 01247 if (move->size < size) { 01248 size = move->size; 01249 } 01250 } 01251 01252 for (move = moves; move != NULL; move = move->next) { 01253 if (move->size == size) return(1); 01254 if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { 01255 res = cuddLinearInPlace(table,(int)move->x,(int)move->y); 01256 if (!res) return(0); 01257 } 01258 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01259 if (!res) return(0); 01260 if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { 01261 res = cuddLinearInPlace(table,(int)move->x,(int)move->y); 01262 if (!res) return(0); 01263 } 01264 } 01265 01266 return(1); 01267 01268 } /* end of ddLinearAndSiftingBackward */
static Move * ddLinearAndSiftingDown | ( | DdManager * | table, | |
int | x, | |||
int | xHigh, | |||
Move * | prevMoves | |||
) | [static] |
Function********************************************************************
Synopsis [Sifts a variable down and applies linear transformations.]
Description [Sifts a variable down and applies linear transformations. Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 1125 of file cuddLinear.c.
01130 { 01131 Move *moves; 01132 Move *move; 01133 int y; 01134 int size, newsize; 01135 int R; /* upper bound on node decrease */ 01136 int limitSize; 01137 int xindex, yindex; 01138 int isolated; 01139 #ifdef DD_DEBUG 01140 int checkR; 01141 int z; 01142 int zindex; 01143 #endif 01144 01145 moves = prevMoves; 01146 /* Initialize R */ 01147 xindex = table->invperm[x]; 01148 limitSize = size = table->keys - table->isolated; 01149 R = 0; 01150 for (y = xHigh; y > x; y--) { 01151 yindex = table->invperm[y]; 01152 if (cuddTestInteract(table,xindex,yindex)) { 01153 isolated = table->vars[yindex]->ref == 1; 01154 R += table->subtables[y].keys - isolated; 01155 } 01156 } 01157 01158 y = cuddNextHigh(table,x); 01159 while (y <= xHigh && size - R < limitSize) { 01160 #ifdef DD_DEBUG 01161 checkR = 0; 01162 for (z = xHigh; z > x; z--) { 01163 zindex = table->invperm[z]; 01164 if (cuddTestInteract(table,xindex,zindex)) { 01165 isolated = table->vars[zindex]->ref == 1; 01166 checkR += table->subtables[z].keys - isolated; 01167 } 01168 } 01169 if (R != checkR) { 01170 (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); 01171 } 01172 #endif 01173 /* Update upper bound on node decrease. */ 01174 yindex = table->invperm[y]; 01175 if (cuddTestInteract(table,xindex,yindex)) { 01176 isolated = table->vars[yindex]->ref == 1; 01177 R -= table->subtables[y].keys - isolated; 01178 } 01179 size = cuddSwapInPlace(table,x,y); 01180 if (size == 0) goto ddLinearAndSiftingDownOutOfMem; 01181 newsize = cuddLinearInPlace(table,x,y); 01182 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; 01183 move = (Move *) cuddDynamicAllocNode(table); 01184 if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; 01185 move->x = x; 01186 move->y = y; 01187 move->next = moves; 01188 moves = move; 01189 move->flags = CUDD_SWAP_MOVE; 01190 if (newsize >= size) { 01191 /* Undo transformation. The transformation we apply is 01192 ** its own inverse. Hence, we just apply the transformation 01193 ** again. 01194 */ 01195 newsize = cuddLinearInPlace(table,x,y); 01196 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; 01197 if (newsize != size) { 01198 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); 01199 } 01200 } else if (cuddTestInteract(table,xindex,yindex)) { 01201 size = newsize; 01202 move->flags = CUDD_LINEAR_TRANSFORM_MOVE; 01203 cuddUpdateInteractionMatrix(table,xindex,yindex); 01204 } 01205 move->size = size; 01206 if ((double) size > (double) limitSize * table->maxGrowth) break; 01207 if (size < limitSize) limitSize = size; 01208 x = y; 01209 y = cuddNextHigh(table,x); 01210 } 01211 return(moves); 01212 01213 ddLinearAndSiftingDownOutOfMem: 01214 while (moves != NULL) { 01215 move = moves->next; 01216 cuddDeallocMove(table, moves); 01217 moves = move; 01218 } 01219 return((Move *) CUDD_OUT_OF_MEM); 01220 01221 } /* end of ddLinearAndSiftingDown */
static Move * ddLinearAndSiftingUp | ( | DdManager * | table, | |
int | y, | |||
int | xLow, | |||
Move * | prevMoves | |||
) | [static] |
Function********************************************************************
Synopsis [Sifts a variable up and applies linear transformations.]
Description [Sifts a variable up and applies linear transformations. Moves y up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 1002 of file cuddLinear.c.
01007 { 01008 Move *moves; 01009 Move *move; 01010 int x; 01011 int size, newsize; 01012 int limitSize; 01013 int xindex, yindex; 01014 int isolated; 01015 int L; /* lower bound on DD size */ 01016 #ifdef DD_DEBUG 01017 int checkL; 01018 int z; 01019 int zindex; 01020 #endif 01021 01022 moves = prevMoves; 01023 yindex = table->invperm[y]; 01024 01025 /* Initialize the lower bound. 01026 ** The part of the DD below y will not change. 01027 ** The part of the DD above y that does not interact with y will not 01028 ** change. The rest may vanish in the best case, except for 01029 ** the nodes at level xLow, which will not vanish, regardless. 01030 */ 01031 limitSize = L = table->keys - table->isolated; 01032 for (x = xLow + 1; x < y; x++) { 01033 xindex = table->invperm[x]; 01034 if (cuddTestInteract(table,xindex,yindex)) { 01035 isolated = table->vars[xindex]->ref == 1; 01036 L -= table->subtables[x].keys - isolated; 01037 } 01038 } 01039 isolated = table->vars[yindex]->ref == 1; 01040 L -= table->subtables[y].keys - isolated; 01041 01042 x = cuddNextLow(table,y); 01043 while (x >= xLow && L <= limitSize) { 01044 xindex = table->invperm[x]; 01045 #ifdef DD_DEBUG 01046 checkL = table->keys - table->isolated; 01047 for (z = xLow + 1; z < y; z++) { 01048 zindex = table->invperm[z]; 01049 if (cuddTestInteract(table,zindex,yindex)) { 01050 isolated = table->vars[zindex]->ref == 1; 01051 checkL -= table->subtables[z].keys - isolated; 01052 } 01053 } 01054 isolated = table->vars[yindex]->ref == 1; 01055 checkL -= table->subtables[y].keys - isolated; 01056 if (L != checkL) { 01057 (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); 01058 } 01059 #endif 01060 size = cuddSwapInPlace(table,x,y); 01061 if (size == 0) goto ddLinearAndSiftingUpOutOfMem; 01062 newsize = cuddLinearInPlace(table,x,y); 01063 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; 01064 move = (Move *) cuddDynamicAllocNode(table); 01065 if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; 01066 move->x = x; 01067 move->y = y; 01068 move->next = moves; 01069 moves = move; 01070 move->flags = CUDD_SWAP_MOVE; 01071 if (newsize >= size) { 01072 /* Undo transformation. The transformation we apply is 01073 ** its own inverse. Hence, we just apply the transformation 01074 ** again. 01075 */ 01076 newsize = cuddLinearInPlace(table,x,y); 01077 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; 01078 #ifdef DD_DEBUG 01079 if (newsize != size) { 01080 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); 01081 } 01082 #endif 01083 } else if (cuddTestInteract(table,xindex,yindex)) { 01084 size = newsize; 01085 move->flags = CUDD_LINEAR_TRANSFORM_MOVE; 01086 cuddUpdateInteractionMatrix(table,xindex,yindex); 01087 } 01088 move->size = size; 01089 /* Update the lower bound. */ 01090 if (cuddTestInteract(table,xindex,yindex)) { 01091 isolated = table->vars[xindex]->ref == 1; 01092 L += table->subtables[y].keys - isolated; 01093 } 01094 if ((double) size > (double) limitSize * table->maxGrowth) break; 01095 if (size < limitSize) limitSize = size; 01096 y = x; 01097 x = cuddNextLow(table,y); 01098 } 01099 return(moves); 01100 01101 ddLinearAndSiftingUpOutOfMem: 01102 while (moves != NULL) { 01103 move = moves->next; 01104 cuddDeallocMove(table, moves); 01105 moves = move; 01106 } 01107 return((Move *) CUDD_OUT_OF_MEM); 01108 01109 } /* end of ddLinearAndSiftingUp */
static int ddLinearUniqueCompare | ( | int * | ptrX, | |
int * | ptrY | |||
) | [static] |
AutomaticStart
Function********************************************************************
Synopsis [Comparison function used by qsort.]
Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]
SideEffects [None]
Definition at line 868 of file cuddLinear.c.
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the order in effect before the moves.]
Description [Given a set of moves, returns the DD heap to the order in effect before the moves. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 1284 of file cuddLinear.c.
01287 { 01288 Move *invmoves = NULL; 01289 Move *move; 01290 Move *invmove; 01291 int size; 01292 01293 for (move = moves; move != NULL; move = move->next) { 01294 invmove = (Move *) cuddDynamicAllocNode(table); 01295 if (invmove == NULL) goto ddUndoMovesOutOfMem; 01296 invmove->x = move->x; 01297 invmove->y = move->y; 01298 invmove->next = invmoves; 01299 invmoves = invmove; 01300 if (move->flags == CUDD_SWAP_MOVE) { 01301 invmove->flags = CUDD_SWAP_MOVE; 01302 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01303 if (!size) goto ddUndoMovesOutOfMem; 01304 } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { 01305 invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; 01306 size = cuddLinearInPlace(table,(int)move->x,(int)move->y); 01307 if (!size) goto ddUndoMovesOutOfMem; 01308 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01309 if (!size) goto ddUndoMovesOutOfMem; 01310 } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ 01311 #ifdef DD_DEBUG 01312 (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); 01313 #endif 01314 invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; 01315 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 01316 if (!size) goto ddUndoMovesOutOfMem; 01317 size = cuddLinearInPlace(table,(int)move->x,(int)move->y); 01318 if (!size) goto ddUndoMovesOutOfMem; 01319 } 01320 invmove->size = size; 01321 } 01322 01323 return(invmoves); 01324 01325 ddUndoMovesOutOfMem: 01326 while (invmoves != NULL) { 01327 move = invmoves->next; 01328 cuddDeallocMove(table, invmoves); 01329 invmoves = move; 01330 } 01331 return((Move *) CUDD_OUT_OF_MEM); 01332 01333 } /* end of ddUndoMoves */
char rcsid [] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $" [static] |
Definition at line 95 of file cuddLinear.c.
int* entry [static] |
Definition at line 98 of file cuddLinear.c.