/**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