#include "reo.h"
Go to the source code of this file.
Defines | |
#define | AddToLinkedList(ppList, pLink) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) |
Functions | |
double | reoReorderSwapAdjacentVars (reo_man *p, int lev0, int fMovingUp) |
#define AddToLinkedList | ( | ppList, | |||
pLink | ) | (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) |
CFile****************************************************************
FileName [reoSwap.c]
PackageName [REO: A specialized DD reordering engine.]
Synopsis [Implementation of the two-variable swap.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 15, 2002.]
Revision [
] DECLARATIONS ///
double reoReorderSwapAdjacentVars | ( | reo_man * | p, | |
int | lev0, | |||
int | fMovingUp | |||
) |
FUNCTION DEFINITIONS ///Function*************************************************************
Synopsis []
Description [Takes the level (lev0) of the plane, which should be swapped with the next plane. Returns the gain using the current cost function.]
SideEffects []
SeeAlso []
Definition at line 43 of file reoSwap.c.
00044 { 00045 // the levels in the decision diagram 00046 int lev1 = lev0 + 1, lev2 = lev0 + 2; 00047 // the new nodes on lev0 00048 reo_unit * pLoop, * pUnit; 00049 // the new nodes on lev1 00050 reo_unit * pNewPlane20, * pNewPlane21, * pNewPlane20R; 00051 reo_unit * pUnitE, * pUnitER, * pUnitT; 00052 // the nodes below lev1 00053 reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T; 00054 reo_unit * pNew1ER, * pNew2ER; 00055 // the old linked lists 00056 reo_unit * pListOld0 = p->pPlanes[lev0].pHead; 00057 reo_unit * pListOld1 = p->pPlanes[lev1].pHead; 00058 // working planes and one more temporary plane 00059 reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0; 00060 reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; 00061 reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; 00062 // various integer variables 00063 int fComp, fCompT, fFound, nWidthCofs, HKey, fInteract, temp, c; 00064 // statistical variables 00065 int nNodesUpMovedDown = 0; 00066 int nNodesDownMovedUp = 0; 00067 int nNodesUnrefRemoved = 0; 00068 int nNodesUnrefAdded = 0; 00069 int nWidthReduction = 0; 00070 double AplWeightTotalLev0; 00071 double AplWeightTotalLev1; 00072 double AplWeightHalf; 00073 double AplWeightPrev; 00074 double AplWeightAfter; 00075 double nCostGain; 00076 00077 // set the old lists 00078 assert( lev0 >= 0 && lev1 < p->nSupp ); 00079 pListOld0 = p->pPlanes[lev0].pHead; 00080 pListOld1 = p->pPlanes[lev1].pHead; 00081 00082 // make sure the planes have nodes 00083 assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes ); 00084 assert( pListOld0 && pListOld1 ); 00085 00086 if ( p->fMinWidth ) 00087 { 00088 // verify that the width parameters are set correctly 00089 reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); 00090 reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); 00091 // start the storage for cofactors 00092 nWidthCofs = 0; 00093 } 00094 else if ( p->fMinApl ) 00095 { 00096 AplWeightPrev = p->nAplCur; 00097 AplWeightAfter = p->nAplCur; 00098 AplWeightTotalLev0 = 0.0; 00099 AplWeightTotalLev1 = 0.0; 00100 } 00101 00102 // check if the planes interact 00103 fInteract = 0; // assume that they do not interact 00104 for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) 00105 { 00106 if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 ) 00107 { 00108 fInteract = 1; 00109 break; 00110 } 00111 // change the level now, this is done for efficiency reasons 00112 pUnit->lev = lev1; 00113 } 00114 00115 // set the new signature for hashing 00116 p->nSwaps++; 00117 if ( !fInteract ) 00118 // if ( 0 ) 00119 { 00120 // perform the swap without interaction 00121 p->nNISwaps++; 00122 00123 // change the levels 00124 if ( p->fMinWidth ) 00125 { 00126 // go through the current lower level, which will become upper 00127 for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) 00128 { 00129 pUnit->lev = lev0; 00130 00131 pUnitER = Unit_Regular(pUnit->pE); 00132 if ( pUnitER->TopRef > lev0 ) 00133 { 00134 if ( pUnitER->Sign != p->nSwaps ) 00135 { 00136 if ( pUnitER->TopRef == lev2 ) 00137 { 00138 pUnitER->TopRef = lev1; 00139 nWidthReduction--; 00140 } 00141 else 00142 { 00143 assert( pUnitER->TopRef == lev1 ); 00144 } 00145 pUnitER->Sign = p->nSwaps; 00146 } 00147 } 00148 00149 pUnitT = pUnit->pT; 00150 if ( pUnitT->TopRef > lev0 ) 00151 { 00152 if ( pUnitT->Sign != p->nSwaps ) 00153 { 00154 if ( pUnitT->TopRef == lev2 ) 00155 { 00156 pUnitT->TopRef = lev1; 00157 nWidthReduction--; 00158 } 00159 else 00160 { 00161 assert( pUnitT->TopRef == lev1 ); 00162 } 00163 pUnitT->Sign = p->nSwaps; 00164 } 00165 } 00166 00167 } 00168 00169 // go through the current upper level, which will become lower 00170 for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) 00171 { 00172 pUnit->lev = lev1; 00173 00174 pUnitER = Unit_Regular(pUnit->pE); 00175 if ( pUnitER->TopRef > lev0 ) 00176 { 00177 if ( pUnitER->Sign != p->nSwaps ) 00178 { 00179 assert( pUnitER->TopRef == lev1 ); 00180 pUnitER->TopRef = lev2; 00181 pUnitER->Sign = p->nSwaps; 00182 nWidthReduction++; 00183 } 00184 } 00185 00186 pUnitT = pUnit->pT; 00187 if ( pUnitT->TopRef > lev0 ) 00188 { 00189 if ( pUnitT->Sign != p->nSwaps ) 00190 { 00191 assert( pUnitT->TopRef == lev1 ); 00192 pUnitT->TopRef = lev2; 00193 pUnitT->Sign = p->nSwaps; 00194 nWidthReduction++; 00195 } 00196 } 00197 } 00198 } 00199 else 00200 { 00201 // for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) 00202 // pUnit->lev = lev1; 00203 for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) 00204 pUnit->lev = lev0; 00205 } 00206 00207 // set the new linked lists, which will be attached to the planes 00208 pListNew0 = pListOld1; 00209 pListNew1 = pListOld0; 00210 00211 if ( p->fMinApl ) 00212 { 00213 AplWeightTotalLev0 = p->pPlanes[lev1].statsCost; 00214 AplWeightTotalLev1 = p->pPlanes[lev0].statsCost; 00215 } 00216 00217 // set the changes in terms of nodes 00218 nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; 00219 nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; 00220 goto finish; 00221 } 00222 p->Signature++; 00223 00224 00225 // two-variable swap is done in three easy steps 00226 // previously I thought that steps (1) and (2) can be merged into one step 00227 // now it is clear that this cannot be done without changing a lot of other stuff... 00228 00229 // (1) walk through the upper level, find units without cofactors in the lower level 00230 // and move them to the new lower level (while adding to the cache) 00231 // (2) walk through the uppoer level, and tranform all the remaning nodes 00232 // while employing cache for the new lower level 00233 // (3) walk through the old lower level, find those nodes whose ref counters are not zero, 00234 // and move them to the new uppoer level, free other nodes 00235 00236 // (1) walk through the upper level, find units without cofactors in the lower level 00237 // and move them to the new lower level (while adding to the cache) 00238 for ( pLoop = pListOld0; pLoop; ) 00239 { 00240 pUnit = pLoop; 00241 pLoop = pLoop->Next; 00242 00243 pUnitE = pUnit->pE; 00244 pUnitER = Unit_Regular(pUnitE); 00245 pUnitT = pUnit->pT; 00246 00247 if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 ) 00248 { 00249 // before after 00250 // 00251 // <p1> 00252 // 0 / \ 1 00253 // / \ 00254 // / \ 00255 // / \ <p2n> 00256 // / \ 0 / \ 1 00257 // / \ / \ 00258 // / \ / \ 00259 // F0 F1 F0 F1 00260 00261 // move to plane-2-new 00262 // nothing changes in the process (cofactors, ref counter, APL weight) 00263 pUnit->lev = lev1; 00264 AddToLinkedList( ppListNew1, pUnit ); 00265 if ( p->fMinApl ) 00266 AplWeightTotalLev1 += pUnit->Weight; 00267 00268 // add to cache - find the cell with different signature (not the current one!) 00269 for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize); 00270 p->HTable[HKey].Sign == p->Signature; 00271 HKey = (HKey+1) % p->nTableSize ); 00272 assert( p->HTable[HKey].Sign != p->Signature ); 00273 p->HTable[HKey].Sign = p->Signature; 00274 p->HTable[HKey].Arg1 = pUnitE; 00275 p->HTable[HKey].Arg2 = pUnitT; 00276 p->HTable[HKey].Arg3 = pUnit; 00277 00278 nNodesUpMovedDown++; 00279 00280 if ( p->fMinWidth ) 00281 { 00282 // update the cofactors's top ref 00283 if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00284 { 00285 assert( pUnitER->TopRef == lev1 ); 00286 pUnitER->TopRefNew = lev2; 00287 if ( pUnitER->Sign != p->nSwaps ) 00288 { 00289 pUnitER->Sign = p->nSwaps; // set the current signature 00290 p->pWidthCofs[ nWidthCofs++ ] = pUnitER; 00291 } 00292 } 00293 if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00294 { 00295 assert( pUnitT->TopRef == lev1 ); 00296 pUnitT->TopRefNew = lev2; 00297 if ( pUnitT->Sign != p->nSwaps ) 00298 { 00299 pUnitT->Sign = p->nSwaps; // set the current signature 00300 p->pWidthCofs[ nWidthCofs++ ] = pUnitT; 00301 } 00302 } 00303 } 00304 } 00305 else 00306 { 00307 // add to the temporary plane 00308 AddToLinkedList( ppListTemp, pUnit ); 00309 } 00310 } 00311 00312 00313 // (2) walk through the uppoer level, and tranform all the remaning nodes 00314 // while employing cache for the new lower level 00315 for ( pLoop = pListTemp; pLoop; ) 00316 { 00317 pUnit = pLoop; 00318 pLoop = pLoop->Next; 00319 00320 pUnitE = pUnit->pE; 00321 pUnitER = Unit_Regular(pUnitE); 00322 pUnitT = pUnit->pT; 00323 fComp = (int)(pUnitER != pUnitE); 00324 00325 // count the amount of weight to reduce the APL of the children of this node 00326 if ( p->fMinApl ) 00327 AplWeightHalf = 0.5 * pUnit->Weight; 00328 00329 // determine what situation is this 00330 if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 ) 00331 { 00332 if ( fComp == 0 ) 00333 { 00334 // before after 00335 // 00336 // <p1> <p1n> 00337 // 0 / \ 1 0 / \ 1 00338 // / \ / \ 00339 // / \ / \ 00340 // <p2> <p2> <p2n> <p2n> 00341 // 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 00342 // / \ / \ / \ / \ 00343 // / \ / \ / \ / \ 00344 // F0 F1 F2 F3 F0 F2 F1 F3 00345 // pNew1E pNew1T pNew2E pNew2T 00346 // 00347 pNew1E = pUnitE->pE; // F0 00348 pNew1T = pUnitT->pE; // F2 00349 00350 pNew2E = pUnitE->pT; // F1 00351 pNew2T = pUnitT->pT; // F3 00352 } 00353 else 00354 { 00355 // before after 00356 // 00357 // <p1> <p1n> 00358 // 0 . \ 1 0 / \ 1 00359 // . \ / \ 00360 // . \ / \ 00361 // <p2> <p2> <p2n> <p2n> 00362 // 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 00363 // / \ / \ . \ . \ 00364 // / \ / \ . \ . \ 00365 // F0 F1 F2 F3 F0 F2 F1 F3 00366 // pNew1E pNew1T pNew2E pNew2T 00367 // 00368 pNew1E = Unit_Not(pUnitER->pE); // F0 00369 pNew1T = pUnitT->pE; // F2 00370 00371 pNew2E = Unit_Not(pUnitER->pT); // F1 00372 pNew2T = pUnitT->pT; // F3 00373 } 00374 // subtract ref counters - on the level P2 00375 pUnitER->n--; 00376 pUnitT->n--; 00377 00378 // mark the change in the APL weights 00379 if ( p->fMinApl ) 00380 { 00381 pUnitER->Weight -= AplWeightHalf; 00382 pUnitT->Weight -= AplWeightHalf; 00383 AplWeightAfter -= pUnit->Weight; 00384 } 00385 } 00386 else if ( pUnitER->lev == lev1 ) 00387 { 00388 if ( fComp == 0 ) 00389 { 00390 // before after 00391 // 00392 // <p1> <p1n> 00393 // 0 / \ 1 0 / \ 1 00394 // / \ / \ 00395 // / \ / \ 00396 // <p2> \ <p2n> <p2n> 00397 // 0 / \ 1 \ 0 / \ 1 0 / \ 1 00398 // / \ \ / \ / \ 00399 // / \ \ / \ / \ 00400 // F0 F1 F3 F0 F3 F1 F3 00401 // pNew1E pNew1T pNew2E pNew2T 00402 // 00403 pNew1E = pUnitER->pE; // F0 00404 pNew1T = pUnitT; // F3 00405 00406 pNew2E = pUnitER->pT; // F1 00407 pNew2T = pUnitT; // F3 00408 } 00409 else 00410 { 00411 // before after 00412 // 00413 // <p1> <p1n> 00414 // 0 . \ 1 0 / \ 1 00415 // . \ / \ 00416 // . \ / \ 00417 // <p2> \ <p2n> <p2n> 00418 // 0 / \ 1 \ 0 . \ 1 0 . \ 1 00419 // / \ \ . \ . \ 00420 // / \ \ . \ . \ 00421 // F0 F1 F3 F0 F3 F1 F3 00422 // pNew1E pNew1T pNew2E pNew2T 00423 // 00424 pNew1E = Unit_Not(pUnitER->pE); // F0 00425 pNew1T = pUnitT; // F3 00426 00427 pNew2E = Unit_Not(pUnitER->pT); // F1 00428 pNew2T = pUnitT; // F3 00429 } 00430 // subtract ref counter - on the level P2 00431 pUnitER->n--; 00432 // subtract ref counter - on other levels 00433 pUnitT->n--; 00434 00435 // mark the change in the APL weights 00436 if ( p->fMinApl ) 00437 { 00438 pUnitER->Weight -= AplWeightHalf; 00439 AplWeightAfter -= AplWeightHalf; 00440 } 00441 } 00442 else if ( pUnitT->lev == lev1 ) 00443 { 00444 // before after 00445 // 00446 // <p1> <p1n> 00447 // 0 / \ 1 0 / \ 1 00448 // / \ / \ 00449 // / \ / \ 00450 // / <p2> <p2n> <p2n> 00451 // / 0 / \ 1 0 / \ 1 0 / \ 1 00452 // / / \ / \ / \ 00453 // / / \ / \ / \ 00454 // F0 F2 F3 F0 F2 F0 F3 00455 // pNew1E pNew1T pNew2E pNew2T 00456 // 00457 pNew1E = pUnitE; // F0 00458 pNew1T = pUnitT->pE; // F2 00459 00460 pNew2E = pUnitE; // F0 00461 pNew2T = pUnitT->pT; // F3 00462 00463 // subtract incoming edge counter - on the level P2 00464 pUnitT->n--; 00465 // subtract ref counter - on other levels 00466 pUnitER->n--; 00467 00468 // mark the change in the APL weights 00469 if ( p->fMinApl ) 00470 { 00471 pUnitT->Weight -= AplWeightHalf; 00472 AplWeightAfter -= AplWeightHalf; 00473 } 00474 } 00475 else 00476 { 00477 assert( 0 ); // should never happen 00478 } 00479 00480 00481 // consider all the cases except the last one 00482 if ( pNew1E == pNew1T ) 00483 { 00484 pNewPlane20 = pNew1T; 00485 00486 if ( p->fMinWidth ) 00487 { 00488 // update the cofactors's top ref 00489 if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00490 { 00491 pNew1T->TopRefNew = lev1; 00492 if ( pNew1T->Sign != p->nSwaps ) 00493 { 00494 pNew1T->Sign = p->nSwaps; // set the current signature 00495 p->pWidthCofs[ nWidthCofs++ ] = pNew1T; 00496 } 00497 } 00498 } 00499 } 00500 else 00501 { 00502 // pNew1T can be complemented 00503 fCompT = Cudd_IsComplement(pNew1T); 00504 if ( fCompT ) 00505 { 00506 pNew1E = Unit_Not(pNew1E); 00507 pNew1T = Unit_Not(pNew1T); 00508 } 00509 00510 // check the hash-table 00511 fFound = 0; 00512 for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); 00513 p->HTable[HKey].Sign == p->Signature; 00514 HKey = (HKey+1) % p->nTableSize ) 00515 if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) 00516 { // the entry is present 00517 // assign this entry 00518 pNewPlane20 = p->HTable[HKey].Arg3; 00519 assert( pNewPlane20->lev == lev1 ); 00520 fFound = 1; 00521 p->HashSuccess++; 00522 break; 00523 } 00524 00525 if ( !fFound ) 00526 { // create the new entry 00527 pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter 00528 pNewPlane20->pE = pNew1E; 00529 pNewPlane20->pT = pNew1T; 00530 pNewPlane20->n = 0; // ref will be added later 00531 pNewPlane20->lev = lev1; 00532 if ( p->fMinWidth ) 00533 { 00534 pNewPlane20->TopRef = lev1; 00535 pNewPlane20->Sign = 0; 00536 } 00537 // set the weight of this node 00538 if ( p->fMinApl ) 00539 pNewPlane20->Weight = 0.0; 00540 00541 // increment ref counters of children 00542 pNew1ER = Unit_Regular(pNew1E); 00543 pNew1ER->n++; // 00544 pNew1T->n++; // 00545 00546 // insert into the data structure 00547 AddToLinkedList( ppListNew1, pNewPlane20 ); 00548 00549 // add this entry to cache 00550 assert( p->HTable[HKey].Sign != p->Signature ); 00551 p->HTable[HKey].Sign = p->Signature; 00552 p->HTable[HKey].Arg1 = pNew1E; 00553 p->HTable[HKey].Arg2 = pNew1T; 00554 p->HTable[HKey].Arg3 = pNewPlane20; 00555 00556 nNodesUnrefAdded++; 00557 00558 if ( p->fMinWidth ) 00559 { 00560 // update the cofactors's top ref 00561 if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00562 { 00563 if ( pNew1ER->Sign != p->nSwaps ) 00564 { 00565 pNew1ER->TopRefNew = lev2; 00566 if ( pNew1ER->Sign != p->nSwaps ) 00567 { 00568 pNew1ER->Sign = p->nSwaps; // set the current signature 00569 p->pWidthCofs[ nWidthCofs++ ] = pNew1ER; 00570 } 00571 } 00572 // otherwise the level is already set correctly 00573 else 00574 { 00575 assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 ); 00576 } 00577 } 00578 // update the cofactors's top ref 00579 if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00580 { 00581 if ( pNew1T->Sign != p->nSwaps ) 00582 { 00583 pNew1T->TopRefNew = lev2; 00584 if ( pNew1T->Sign != p->nSwaps ) 00585 { 00586 pNew1T->Sign = p->nSwaps; // set the current signature 00587 p->pWidthCofs[ nWidthCofs++ ] = pNew1T; 00588 } 00589 } 00590 // otherwise the level is already set correctly 00591 else 00592 { 00593 assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 ); 00594 } 00595 } 00596 } 00597 } 00598 00599 if ( p->fMinApl ) 00600 { 00601 // increment the weight of this node 00602 pNewPlane20->Weight += AplWeightHalf; 00603 // mark the change in the APL weight 00604 AplWeightAfter += AplWeightHalf; 00605 // update the total weight of this level 00606 AplWeightTotalLev1 += AplWeightHalf; 00607 } 00608 00609 if ( fCompT ) 00610 pNewPlane20 = Unit_Not(pNewPlane20); 00611 } 00612 00613 if ( pNew2E == pNew2T ) 00614 { 00615 pNewPlane21 = pNew2T; 00616 00617 if ( p->fMinWidth ) 00618 { 00619 // update the cofactors's top ref 00620 if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00621 { 00622 pNew2T->TopRefNew = lev1; 00623 if ( pNew2T->Sign != p->nSwaps ) 00624 { 00625 pNew2T->Sign = p->nSwaps; // set the current signature 00626 p->pWidthCofs[ nWidthCofs++ ] = pNew2T; 00627 } 00628 } 00629 } 00630 } 00631 else 00632 { 00633 assert( !Cudd_IsComplement(pNew2T) ); 00634 00635 // check the hash-table 00636 fFound = 0; 00637 for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); 00638 p->HTable[HKey].Sign == p->Signature; 00639 HKey = (HKey+1) % p->nTableSize ) 00640 if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) 00641 { // the entry is present 00642 // assign this entry 00643 pNewPlane21 = p->HTable[HKey].Arg3; 00644 assert( pNewPlane21->lev == lev1 ); 00645 fFound = 1; 00646 p->HashSuccess++; 00647 break; 00648 } 00649 00650 if ( !fFound ) 00651 { // create the new entry 00652 pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter 00653 pNewPlane21->pE = pNew2E; 00654 pNewPlane21->pT = pNew2T; 00655 pNewPlane21->n = 0; // ref will be added later 00656 pNewPlane21->lev = lev1; 00657 if ( p->fMinWidth ) 00658 { 00659 pNewPlane21->TopRef = lev1; 00660 pNewPlane21->Sign = 0; 00661 } 00662 // set the weight of this node 00663 if ( p->fMinApl ) 00664 pNewPlane21->Weight = 0.0; 00665 00666 // increment ref counters of children 00667 pNew2ER = Unit_Regular(pNew2E); 00668 pNew2ER->n++; // 00669 pNew2T->n++; // 00670 00671 // insert into the data structure 00672 // reoUnitsAddUnitToPlane( &P2new, pNewPlane21 ); 00673 AddToLinkedList( ppListNew1, pNewPlane21 ); 00674 00675 // add this entry to cache 00676 assert( p->HTable[HKey].Sign != p->Signature ); 00677 p->HTable[HKey].Sign = p->Signature; 00678 p->HTable[HKey].Arg1 = pNew2E; 00679 p->HTable[HKey].Arg2 = pNew2T; 00680 p->HTable[HKey].Arg3 = pNewPlane21; 00681 00682 nNodesUnrefAdded++; 00683 00684 00685 if ( p->fMinWidth ) 00686 { 00687 // update the cofactors's top ref 00688 if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00689 { 00690 if ( pNew2ER->Sign != p->nSwaps ) 00691 { 00692 pNew2ER->TopRefNew = lev2; 00693 if ( pNew2ER->Sign != p->nSwaps ) 00694 { 00695 pNew2ER->Sign = p->nSwaps; // set the current signature 00696 p->pWidthCofs[ nWidthCofs++ ] = pNew2ER; 00697 } 00698 } 00699 // otherwise the level is already set correctly 00700 else 00701 { 00702 assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 ); 00703 } 00704 } 00705 // update the cofactors's top ref 00706 if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00707 { 00708 if ( pNew2T->Sign != p->nSwaps ) 00709 { 00710 pNew2T->TopRefNew = lev2; 00711 if ( pNew2T->Sign != p->nSwaps ) 00712 { 00713 pNew2T->Sign = p->nSwaps; // set the current signature 00714 p->pWidthCofs[ nWidthCofs++ ] = pNew2T; 00715 } 00716 } 00717 // otherwise the level is already set correctly 00718 else 00719 { 00720 assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 ); 00721 } 00722 } 00723 } 00724 } 00725 00726 if ( p->fMinApl ) 00727 { 00728 // increment the weight of this node 00729 pNewPlane21->Weight += AplWeightHalf; 00730 // mark the change in the APL weight 00731 AplWeightAfter += AplWeightHalf; 00732 // update the total weight of this level 00733 AplWeightTotalLev1 += AplWeightHalf; 00734 } 00735 } 00736 // in all cases, the node will be added to the plane-1 00737 // this should be the same node (pUnit) as was originally there 00738 // because it is referenced by the above nodes 00739 00740 assert( !Cudd_IsComplement(pNewPlane21) ); 00741 // should be the case; otherwise reordering is not a local operation 00742 00743 pUnit->pE = pNewPlane20; 00744 pUnit->pT = pNewPlane21; 00745 assert( pUnit->lev == lev0 ); 00746 // reference counter remains the same; the APL weight remains the same 00747 00748 // increment ref counters of children 00749 pNewPlane20R = Unit_Regular(pNewPlane20); 00750 pNewPlane20R->n++; 00751 pNewPlane21->n++; 00752 00753 // insert into the data structure 00754 AddToLinkedList( ppListNew0, pUnit ); 00755 if ( p->fMinApl ) 00756 AplWeightTotalLev0 += pUnit->Weight; 00757 } 00758 00759 // (3) walk through the old lower level, find those nodes whose ref counters are not zero, 00760 // and move them to the new uppoer level, free other nodes 00761 for ( pLoop = pListOld1; pLoop; ) 00762 { 00763 pUnit = pLoop; 00764 pLoop = pLoop->Next; 00765 if ( pUnit->n ) 00766 { 00767 assert( !p->fMinApl || pUnit->Weight > 0.0 ); 00768 // the node should be added to the new level 00769 // no need to check the hash table 00770 pUnit->lev = lev0; 00771 AddToLinkedList( ppListNew0, pUnit ); 00772 if ( p->fMinApl ) 00773 AplWeightTotalLev0 += pUnit->Weight; 00774 00775 nNodesDownMovedUp++; 00776 00777 if ( p->fMinWidth ) 00778 { 00779 pUnitER = Unit_Regular(pUnit->pE); 00780 pUnitT = pUnit->pT; 00781 00782 // update the cofactors's top ref 00783 if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00784 { 00785 pUnitER->TopRefNew = lev1; 00786 if ( pUnitER->Sign != p->nSwaps ) 00787 { 00788 pUnitER->Sign = p->nSwaps; // set the current signature 00789 p->pWidthCofs[ nWidthCofs++ ] = pUnitER; 00790 } 00791 } 00792 if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels 00793 { 00794 pUnitT->TopRefNew = lev1; 00795 if ( pUnitT->Sign != p->nSwaps ) 00796 { 00797 pUnitT->Sign = p->nSwaps; // set the current signature 00798 p->pWidthCofs[ nWidthCofs++ ] = pUnitT; 00799 } 00800 } 00801 } 00802 } 00803 else 00804 { 00805 assert( !p->fMinApl || pUnit->Weight == 0.0 ); 00806 // decrement reference counters of children 00807 pUnitER = Unit_Regular(pUnit->pE); 00808 pUnitT = pUnit->pT; 00809 pUnitER->n--; 00810 pUnitT->n--; 00811 // the node should be thrown away 00812 reoUnitsRecycleUnit( p, pUnit ); 00813 nNodesUnrefRemoved++; 00814 } 00815 } 00816 00817 finish: 00818 00819 // attach the new levels to the planes 00820 p->pPlanes[lev0].pHead = pListNew0; 00821 p->pPlanes[lev1].pHead = pListNew1; 00822 00823 // swap the sift status 00824 temp = p->pPlanes[lev0].fSifted; 00825 p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted; 00826 p->pPlanes[lev1].fSifted = temp; 00827 00828 // swap variables in the variable map 00829 if ( p->pOrderInt ) 00830 { 00831 temp = p->pOrderInt[lev0]; 00832 p->pOrderInt[lev0] = p->pOrderInt[lev1]; 00833 p->pOrderInt[lev1] = temp; 00834 } 00835 00836 // adjust the node profile 00837 p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp); 00838 p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded; 00839 p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded; 00840 00841 // adjust the node profile on this level 00842 if ( p->fMinWidth ) 00843 { 00844 for ( c = 0; c < nWidthCofs; c++ ) 00845 { 00846 if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef ) 00847 { 00848 p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; 00849 nWidthReduction--; 00850 } 00851 else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef ) 00852 { 00853 p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; 00854 nWidthReduction++; 00855 } 00856 } 00857 // verify that the profile is okay 00858 reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); 00859 reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); 00860 00861 // compute the total gain in terms of width 00862 nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction; 00863 // adjust the width on this level 00864 p->pPlanes[lev1].statsWidth -= (int)nCostGain; 00865 // set the cost 00866 p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth; 00867 } 00868 else if ( p->fMinApl ) 00869 { 00870 // compute the total gain in terms of APL 00871 nCostGain = AplWeightPrev - AplWeightAfter; 00872 // make sure that the ALP is updated correctly 00873 // assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain == 00874 // AplWeightTotalLev0 + AplWeightTotalLev1 ); 00875 // adjust the profile 00876 p->pPlanes[lev0].statsApl = AplWeightTotalLev0; 00877 p->pPlanes[lev1].statsApl = AplWeightTotalLev1; 00878 // set the cost 00879 p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl; 00880 p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl; 00881 } 00882 else 00883 { 00884 // compute the total gain in terms of the number of nodes 00885 nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded; 00886 // adjust the profile (adjusted above) 00887 // set the cost 00888 p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes; 00889 p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes; 00890 } 00891 00892 return nCostGain; 00893 }