| /**CFile**************************************************************** |
| |
| FileName [reoSift.c] |
| |
| PackageName [REO: A specialized DD reordering engine.] |
| |
| Synopsis [Implementation of the sifting algorihtm.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - October 15, 2002.] |
| |
| Revision [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "reo.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the variable sifting algorithm.] |
| |
| Description [Performs a sequence of adjacent variable swaps known as "sifting". |
| Uses the cost functions determined by the flag.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void reoReorderSift( reo_man * p ) |
| { |
| double CostCurrent; // the cost of the current permutation |
| double CostLimit; // the maximum increase in cost that can be tolerated |
| double CostBest; // the best cost |
| int BestQ; // the best position |
| int VarCurrent; // the current variable to move |
| int q; // denotes the current position of the variable |
| int c; // performs the loops over variables until all of them are sifted |
| int v; // used for other purposes |
| |
| assert( p->nSupp > 0 ); |
| |
| // set the current cost depending on the minimization criteria |
| if ( p->fMinWidth ) |
| CostCurrent = p->nWidthCur; |
| else if ( p->fMinApl ) |
| CostCurrent = p->nAplCur; |
| else |
| CostCurrent = p->nNodesCur; |
| |
| // find the upper bound on tbe cost growth |
| CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent); |
| |
| // perform sifting for each of p->nSupp variables |
| for ( c = 0; c < p->nSupp; c++ ) |
| { |
| // select the current variable to be the one with the largest number of nodes that is not sifted yet |
| VarCurrent = -1; |
| CostBest = -1.0; |
| for ( v = 0; v < p->nSupp; v++ ) |
| { |
| p->pVarCosts[v] = REO_HIGH_VALUE; |
| if ( !p->pPlanes[v].fSifted ) |
| { |
| // VarCurrent = v; |
| // if ( CostBest < p->pPlanes[v].statsCost ) |
| if ( CostBest < p->pPlanes[v].statsNodes ) |
| { |
| // CostBest = p->pPlanes[v].statsCost; |
| CostBest = p->pPlanes[v].statsNodes; |
| VarCurrent = v; |
| } |
| |
| } |
| } |
| assert( VarCurrent != -1 ); |
| // mark this variable as sifted |
| p->pPlanes[VarCurrent].fSifted = 1; |
| |
| // set the current value |
| p->pVarCosts[VarCurrent] = CostCurrent; |
| |
| // set the best cost |
| CostBest = CostCurrent; |
| BestQ = VarCurrent; |
| |
| // determine which way to move the variable first (up or down) |
| // the rationale is that if we move the shorter way first |
| // it is more likely that the best position will be found on the longer way |
| // and the reverse movement (to take the best position) will be faster |
| if ( VarCurrent < p->nSupp/2 ) // move up first, then down |
| { |
| // set the total cost on all levels above the current level |
| p->pPlanes[0].statsCostAbove = 0; |
| for ( v = 1; v <= VarCurrent; v++ ) |
| p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; |
| // set the total cost on all levels below the current level |
| p->pPlanes[p->nSupp].statsCostBelow = 0; |
| for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) |
| p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; |
| |
| assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + |
| p->pPlanes[VarCurrent].statsCost + |
| p->pPlanes[VarCurrent].statsCostBelow ); |
| |
| // move up |
| for ( q = VarCurrent-1; q >= 0; q-- ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); |
| // now q points to the position of this var in the order |
| p->pVarCosts[q] = CostCurrent; |
| // update the lower bound (assuming that for level q+1 it is set correctly) |
| p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; |
| // check the upper bound |
| if ( CostCurrent >= CostLimit ) |
| break; |
| // check the lower bound |
| if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) |
| break; |
| // update the best cost |
| if ( CostBest > CostCurrent ) |
| { |
| CostBest = CostCurrent; |
| BestQ = q; |
| // adjust node limit |
| CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); |
| } |
| |
| // when we are reordering for width or APL, it may happen that |
| // the number of nodes has grown above certain limit, |
| // in which case we have to resize the data structures |
| if ( p->fMinWidth || p->fMinApl ) |
| { |
| if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) |
| { |
| // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); |
| reoResizeStructures( p, 0, p->nNodesCur, 0 ); |
| } |
| } |
| } |
| // fix the plane index |
| if ( q == -1 ) |
| q++; |
| // now p points to the position of this var in the order |
| |
| // move down |
| for ( ; q < p->nSupp-1; ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); |
| q++; // change q to point to the position of this var in the order |
| // sanity check: the number of nodes on the back pass should be the same |
| if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) |
| printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); |
| p->pVarCosts[q] = CostCurrent; |
| // update the lower bound (assuming that for level q-1 it is set correctly) |
| p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; |
| // check the bounds only if the variable already reached its previous position |
| if ( q >= BestQ ) |
| { |
| // check the upper bound |
| if ( CostCurrent >= CostLimit ) |
| break; |
| // check the lower bound |
| if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) |
| break; |
| } |
| // update the best cost |
| if ( CostBest >= CostCurrent ) |
| { |
| CostBest = CostCurrent; |
| BestQ = q; |
| // adjust node limit |
| CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); |
| } |
| |
| // when we are reordering for width or APL, it may happen that |
| // the number of nodes has grown above certain limit, |
| // in which case we have to resize the data structures |
| if ( p->fMinWidth || p->fMinApl ) |
| { |
| if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) |
| { |
| // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); |
| reoResizeStructures( p, 0, p->nNodesCur, 0 ); |
| } |
| } |
| } |
| // move the variable up from the given position (q) to the best position (BestQ) |
| assert( q >= BestQ ); |
| for ( ; q > BestQ; q-- ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 ); |
| // sanity check: the number of nodes on the back pass should be the same |
| if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON ) |
| { |
| printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); |
| fflush(stdout); |
| } |
| } |
| } |
| else // move down first, then up |
| { |
| // set the current number of nodes on all levels above the given level |
| p->pPlanes[0].statsCostAbove = 0; |
| for ( v = 1; v <= VarCurrent; v++ ) |
| p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; |
| // set the current number of nodes on all levels below the given level |
| p->pPlanes[p->nSupp].statsCostBelow = 0; |
| for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) |
| p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; |
| |
| assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + |
| p->pPlanes[VarCurrent].statsCost + |
| p->pPlanes[VarCurrent].statsCostBelow ); |
| |
| // move down |
| for ( q = VarCurrent; q < p->nSupp-1; ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); |
| q++; // change q to point to the position of this var in the order |
| p->pVarCosts[q] = CostCurrent; |
| // update the lower bound (assuming that for level q-1 it is set correctly) |
| p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; |
| // check the upper bound |
| if ( CostCurrent >= CostLimit ) |
| break; |
| // check the lower bound |
| if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) |
| break; |
| // update the best cost |
| if ( CostBest > CostCurrent ) |
| { |
| CostBest = CostCurrent; |
| BestQ = q; |
| // adjust node limit |
| CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); |
| } |
| |
| // when we are reordering for width or APL, it may happen that |
| // the number of nodes has grown above certain limit, |
| // in which case we have to resize the data structures |
| if ( p->fMinWidth || p->fMinApl ) |
| { |
| if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) |
| { |
| // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); |
| reoResizeStructures( p, 0, p->nNodesCur, 0 ); |
| } |
| } |
| } |
| |
| // move up |
| for ( --q; q >= 0; q-- ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); |
| // now q points to the position of this var in the order |
| // sanity check: the number of nodes on the back pass should be the same |
| if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) |
| printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); |
| p->pVarCosts[q] = CostCurrent; |
| // update the lower bound (assuming that for level q+1 it is set correctly) |
| p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; |
| // check the bounds only if the variable already reached its previous position |
| if ( q <= BestQ ) |
| { |
| // check the upper bound |
| if ( CostCurrent >= CostLimit ) |
| break; |
| // check the lower bound |
| if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) |
| break; |
| } |
| // update the best cost |
| if ( CostBest >= CostCurrent ) |
| { |
| CostBest = CostCurrent; |
| BestQ = q; |
| // adjust node limit |
| CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); |
| } |
| |
| // when we are reordering for width or APL, it may happen that |
| // the number of nodes has grown above certain limit, |
| // in which case we have to resize the data structures |
| if ( p->fMinWidth || p->fMinApl ) |
| { |
| if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) |
| { |
| // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); |
| reoResizeStructures( p, 0, p->nNodesCur, 0 ); |
| } |
| } |
| } |
| // fix the plane index |
| if ( q == -1 ) |
| q++; |
| // now q points to the position of this var in the order |
| // move the variable down from the given position (q) to the best position (BestQ) |
| assert( q <= BestQ ); |
| for ( ; q < BestQ; q++ ) |
| { |
| CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); |
| // sanity check: the number of nodes on the back pass should be the same |
| if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON ) |
| { |
| printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); |
| fflush(stdout); |
| } |
| } |
| } |
| assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON ); |
| |
| // update the cost |
| if ( p->fMinWidth ) |
| p->nWidthCur = (int)CostBest; |
| else if ( p->fMinApl ) |
| p->nAplCur = CostCurrent; |
| else |
| p->nNodesCur = (int)CostBest; |
| } |
| |
| // remove the sifted attributes if any |
| for ( v = 0; v < p->nSupp; v++ ) |
| p->pPlanes[v].fSifted = 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| ABC_NAMESPACE_IMPL_END |
| |