Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members

btreeanneal.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002 ***    
00003 *** Copyright (c) 1995-2000 Regents of the University of California,
00004 ***               Andrew E. Caldwell, Andrew B. Kahng and Igor L. Markov
00005 *** Copyright (c) 2000-2004 Regents of the University of Michigan,
00006 ***               Saurabh N. Adya, Jarrod A. Roy and Igor L. Markov
00007 ***
00008 ***  Contact author(s): abk@cs.ucsd.edu, imarkov@umich.edu
00009 ***  Original Affiliation:   UCLA, Computer Science Department,
00010 ***                          Los Angeles, CA 90095-1596 USA
00011 ***
00012 ***  Permission is hereby granted, free of charge, to any person obtaining 
00013 ***  a copy of this software and associated documentation files (the
00014 ***  "Software"), to deal in the Software without restriction, including
00015 ***  without limitation 
00016 ***  the rights to use, copy, modify, merge, publish, distribute, sublicense, 
00017 ***  and/or sell copies of the Software, and to permit persons to whom the 
00018 ***  Software is furnished to do so, subject to the following conditions:
00019 ***
00020 ***  The above copyright notice and this permission notice shall be included
00021 ***  in all copies or substantial portions of the Software.
00022 ***
00023 *** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00024 *** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00025 *** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
00026 *** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
00027 *** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
00028 *** OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
00029 *** THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00030 ***
00031 ***
00032 ***************************************************************************/
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 #include "btreeanneal.h"
00048 #include "btreecompact.h"
00049 #include "basepacking.h"
00050 #include "mixedpacking.h"
00051 #include "mixedpackingfromdb.h"
00052 #include "pltobtree.h"
00053 
00054 #include "debugflags.h"
00055 
00056 // parquet data-structures, commented out in order to compile
00057 // #include "FPcommon.h"
00058 // #include "DB.h"
00059 // #include "AnalytSolve.h"
00060 // #include "CommandLine.h"
00061 #include "allparquet.h"
00062 
00063 #include <cmath>
00064 #include <cfloat>
00065 #include <algorithm>
00066 #include <iterator>
00067 using namespace std;
00068 
00069 using parquetfp::Nodes;
00070 using parquetfp::DB;
00071 using parquetfp::Command_Line;
00072 using parquetfp::AnalytSolve;
00073 
00074 // ========================================================
00075 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00076    MixedBlockInfoType& nBlockinfo)
00077    : BaseAnnealer(),
00078      _blockinfo_cleaner(NULL),
00079      _blockinfo(nBlockinfo),
00080      blockinfo(nBlockinfo),
00081      in_curr_solution(_blockinfo.currDimensions),
00082      in_next_solution(_blockinfo.currDimensions),
00083      in_best_solution(_blockinfo.currDimensions),
00084      _slackEval(NULL)
00085 {}
00086 // --------------------------------------------------------
00087 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00088    MixedBlockInfoType& nBlockinfo,
00089    const Command_Line *const params,
00090    DB *const db)
00091    : BaseAnnealer(params, db),
00092      _blockinfo_cleaner(NULL),
00093      _blockinfo(nBlockinfo),
00094      blockinfo(nBlockinfo),
00095      in_curr_solution(_blockinfo.currDimensions),
00096      in_next_solution(_blockinfo.currDimensions),
00097      in_best_solution(_blockinfo.currDimensions),
00098      _slackEval(new BTreeSlackEval(in_curr_solution))
00099 {
00100    constructor_core();
00101 }
00102 // --------------------------------------------------------
00103 BTreeAreaWireAnnealer::BTreeAreaWireAnnealer(
00104    const Command_Line *const params,
00105    DB *const db)
00106    : BaseAnnealer(params, db),
00107      _blockinfo_cleaner(static_cast<MixedBlockInfoType*>
00108                         (new MixedBlockInfoTypeFromDB(*db))),
00109      _blockinfo(*_blockinfo_cleaner),
00110      blockinfo(_blockinfo),
00111      in_curr_solution(_blockinfo.currDimensions),
00112      in_next_solution(_blockinfo.currDimensions),
00113      in_best_solution(_blockinfo.currDimensions),
00114      _slackEval(new BTreeSlackEval(in_curr_solution))
00115 {
00116    constructor_core();
00117 }
00118 // --------------------------------------------------------
00119 void BTreeAreaWireAnnealer::constructor_core()
00120 {
00121    // initialize the orientation map
00122    _physicalOrient.resize(in_curr_solution.NUM_BLOCKS);
00123    for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00124    {      
00125       _physicalOrient[i].resize(blockinfo.ORIENT_NUM);
00126       for (int theta = 0; theta < blockinfo.ORIENT_NUM; theta++)
00127       {
00128          parquetfp::Node& currBlock = _db->getNodes()->getNode(i);
00129          if (currBlock.isOrientFixed())
00130             _physicalOrient[i][theta] = parquetfp::N;
00131          else
00132             _physicalOrient[i][theta] = parquetfp::ORIENT(theta);
00133       }
00134    }
00135    
00136    // generate an initial solution
00137    GenerateRandomSoln(in_curr_solution, blockinfo.currDimensions.blocknum());
00138    in_best_solution = in_curr_solution;
00139    in_next_solution = in_curr_solution;
00140    
00141    // initialize the orientations of nodes in *_db if necessary
00142    for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00143    {
00144       int initOrient = int(in_curr_solution.tree[i].orient);
00145       initOrient = _physicalOrient[i][initOrient];
00146       
00147       double initWidth = in_curr_solution.width(i);
00148       double initHeight = in_curr_solution.height(i);
00149       
00150       _db->getNodes()->changeOrient(i, parquetfp::ORIENT(initOrient),
00151                                     *(_db->getNets()));
00152       _db->getNodes()->putNodeWidth(i, initWidth);
00153       _db->getNodes()->putNodeHeight(i, initHeight);
00154    }
00155 
00156 
00157    // -----debug messages-----
00158    for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00159    {
00160       for (int theta = 0; theta < blockinfo.ORIENT_NUM; theta++)
00161          if ((_db->getNodes()->getNode(i)).isOrientFixed() &&
00162              int(in_curr_solution.tree[i].orient) != 0)
00163          {
00164             cout << "ctor: orient of block[" << i << "] should be \"n\"" << endl;
00165             printf("in_curr_solution:orient %d\n",
00166                    int(in_curr_solution.tree[i].orient));
00167             cin.get();
00168          }
00169       
00170       if (_params->minWL && (int(in_curr_solution.tree[i].orient) !=
00171                              int(_db->getNodes()->getNode(i).getOrient())))
00172       {
00173          cout << "ctor: orient of block[" << i << "] is not consistent" << endl;
00174          printf("in_curr_solution:orient %d vs. _db->orient: %d\n",
00175                 int(in_curr_solution.tree[i].orient),
00176                 int(_db->getNodes()->getNode(i).getOrient()));
00177          cin.get();
00178       }
00179       
00180       int theta = in_curr_solution.tree[i].orient;
00181       if (fabs(in_curr_solution.width(i) - blockinfo.currDimensions[i].width[theta]) > 1e-6)
00182       {
00183          printf("ctor: width of block[%d] is not consistent.  in_curr_soln: %.2f vs. blockinfo: %.2f\n",
00184                 i, in_curr_solution.width(i), blockinfo.currDimensions[i].width[theta]);
00185          cin.get();
00186       }
00187       
00188       if (fabs(in_curr_solution.height(i) - blockinfo.currDimensions[i].height[theta]) > 1e-6)
00189       {
00190          printf("ctor: height of block[%d] is not consistent.  in_curr_soln: %.2f vs. blockinfo: %.2f\n",
00191                 i, in_curr_solution.height(i), blockinfo.currDimensions[i].height[theta]);
00192          cin.get();
00193       }
00194       
00195       if (_params->minWL && fabs(in_curr_solution.width(i) - _db->getNodes()->getNodeWidth(i)) > 1e-6)
00196       {
00197          printf("ctor: width of block[%d] is not consistent.  in_curr_solution: %.2f vs._db: %.2f\n",
00198                 i, in_curr_solution.width(i), _db->getNodes()->getNodeWidth(i));
00199          cin.get();
00200       }
00201    }
00202 }
00203 // --------------------------------------------------------
00204 bool BTreeAreaWireAnnealer::go()
00205 {      
00206    Timer T;
00207    T.stop();
00208 
00209    DBfromSoln(in_curr_solution);
00210 
00211    T.start(0.0);
00212    bool success = false;
00213    if (in_curr_solution.NUM_BLOCKS > 1)
00214       success = anneal();
00215    else
00216       success = packOneBlock();
00217    T.stop();
00218 
00219    annealTime += T.getUserTime();
00220 
00221    // update *_db for locs, dimensions and slacks
00222    DBfromSoln(in_curr_solution);
00223    in_best_solution = in_curr_solution;
00224 
00225    // print solutions
00226    SolutionInfo currSoln;
00227    currSoln.area = in_curr_solution.totalArea();
00228    currSoln.width = in_curr_solution.totalWidth();
00229    currSoln.height = in_curr_solution.totalHeight();
00230    currSoln.HPWL = _db->evalHPWL();
00231    printResults(T, currSoln);
00232 
00233    return success;
00234 }
00235 // --------------------------------------------------------
00236 void BTreeAreaWireAnnealer::DBfromSoln(const BTree& soln)
00237 {
00238    _db->updatePlacement(const_cast<vector<double>&>(soln.xloc()),
00239                         const_cast<vector<double>&>(soln.yloc()));
00240    for (int i = 0; i < soln.NUM_BLOCKS; i++)
00241    {
00242       parquetfp::ORIENT newOrient =
00243          parquetfp::ORIENT(soln.tree[i].orient);
00244       _db->getNodes()->changeOrient(i, newOrient, *(_db->getNets()));
00245       _db->getNodes()->putNodeWidth(i, soln.width(i));
00246       _db->getNodes()->putNodeHeight(i, soln.height(i));
00247    }
00248    
00249    _slackEval->evaluateSlacks(soln);
00250 
00251    int blocknum = soln.NUM_BLOCKS;
00252    vector<double> xSlacks(blocknum); // % x-slacks
00253    vector<double> ySlacks(blocknum); // % y-slacks
00254    double totalWidth = soln.totalWidth();
00255    double totalHeight = soln.totalHeight();
00256    for (int i = 0; i < blocknum; i++)
00257    {
00258       xSlacks[i] = (_slackEval->xSlack()[i] / totalWidth) * 100;
00259       ySlacks[i] = (_slackEval->ySlack()[i] / totalHeight) * 100;
00260    }      
00261    _db->updateSlacks(xSlacks, ySlacks);
00262 
00263 #ifdef PARQUET_DEBUG_HAYWARD_ASSERT_BTREEANNEAL
00264    for (int i = 0; i < blocknum; i++)
00265    {
00266       int theta = soln.tree[i].orient;
00267       if (theta != _physicalOrient[i][theta])
00268       {
00269          printf("block: %d theta: %d physicalOrient: %d\n",
00270                 i, theta, _physicalOrient[i][theta]);
00271          cin.get();
00272       }
00273    }   
00274 #endif
00275 }
00276 // --------------------------------------------------------
00277 bool BTreeAreaWireAnnealer::packOneBlock()
00278 {
00279    const double blocksArea = in_curr_solution.blockArea();
00280    const double reqdAR = _params->reqdAR;
00281    const double reqdArea = blocksArea * (1+(_params->maxWS/100.0));
00282    const double reqdWidth = sqrt(reqdArea * reqdAR);
00283    const double reqdHeight = reqdWidth / reqdAR;
00284    
00285    const vector<double> defaultXloc(1, 0); // 1 copy of "0"
00286    const vector<double> defaultYloc(1, 0);
00287    const int defaultOrient = 0;
00288 
00289    cout << "Only one block is detected, deterministic algo used." << endl;
00290    if (_params->reqdAR != FREE_OUTLINE)
00291       cout << "outline width: " << reqdWidth
00292            << " outline height: " << reqdHeight << endl;
00293       
00294    int bestOrient = defaultOrient; 
00295    double bestHPWL = basepacking_h::Dimension::INFTY;
00296    bool success = false;
00297    for (int theta = 0;
00298         theta < basepacking_h::Dimension::ORIENT_NUM; theta++) 
00299    {
00300       in_curr_solution.rotate(0, theta);
00301 
00302       double blockWidth = in_curr_solution.width(0);
00303       double blockHeight = in_curr_solution.height(0);
00304       bool fitsInside = ((_params->reqdAR == FREE_OUTLINE) ||
00305                          ((blockWidth <= reqdWidth) &&
00306                           (blockHeight <= reqdHeight)));
00307 
00308       cout << "orient: " << theta
00309            << " width: " << blockWidth
00310            << " height: " << blockHeight
00311            << " inside: " << ((fitsInside)? "T" : "F");
00312       
00313       success = success || fitsInside;
00314       if (fitsInside && _params->minWL)
00315       {
00316          DBfromSoln(in_curr_solution);
00317          double currHPWL = _db->evalHPWL();
00318          
00319          cout << " HPWL: " << currHPWL;
00320          if (currHPWL < bestHPWL)
00321          {
00322             bestOrient = theta;
00323             bestHPWL = currHPWL;
00324          }
00325       }
00326       else if (fitsInside)
00327          bestOrient = theta;
00328       
00329       cout << endl;
00330    }
00331 
00332    in_curr_solution.rotate(0, bestOrient);
00333    DBfromSoln(in_curr_solution);
00334 
00335    return success;
00336 }
00337 // ---------------------------------------------------------
00338 bool BTreeAreaWireAnnealer::anneal()
00339 {
00340    // options
00341    bool budgetTime = _params->budgetTime;
00342    double seconds = _params->seconds;  
00343    bool minWL = _params->minWL;
00344 
00345    // input params
00346    double wireWeight = _params->wireWeight;
00347    double areaWeight = _params->areaWeight;
00348    double ARWeight = max(1 - areaWeight - wireWeight, 0.0);
00349 
00350    // input params
00351    double blocksArea = _db->getNodesArea();
00352    double size = in_curr_solution.NUM_BLOCKS;
00353   
00354    double currTime = _params->startTime;
00355 
00356    // if any constraint is imposed
00357    const double reqdAR = _params->reqdAR;
00358    // const double reqdArea = blocksArea * (1+((_params->maxWS-1)/100.0));
00359    // const double reqdWidth = sqrt(reqdArea*reqdAR);
00360    // const double reqdHeight = reqdWidth/reqdAR;
00361 
00362    // const double real_reqdAR = _params->reqdAR;
00363    const double real_reqdArea = blocksArea * (1+(_params->maxWS/100.0));
00364    const double real_reqdWidth = sqrt(real_reqdArea*reqdAR);
00365    const double real_reqdHeight = real_reqdWidth / reqdAR;
00366 
00367    // save attributes of the best solution
00368    // double bestArea = DBL_MAX;
00369    // double bestHPWL = DBL_MAX;
00370    
00371    // global counters and book-keepers
00372    int move = UNINITIALIZED;
00373    int count = 0;
00374    int prev_move = UNINITIALIZED;
00375    
00376    unsigned int timeChangeCtr = 0;
00377    unsigned int moveSelect = UNSIGNED_UNINITIALIZED;
00378    unsigned int iter = UNSIGNED_UNINITIALIZED;
00379    unsigned int masterMoveSel = 0;
00380    
00381    bool moveAccepted = false; 
00382    bool brokeFromLoop = false;
00383 
00384    double unit=0, total=seconds, percent=1;
00385    unsigned int moves = 2000;
00386 
00387    Timer looptm;
00388    looptm.stop();
00389 
00390    _db->updatePlacement(const_cast<vector<double>&>(in_curr_solution.xloc()),
00391                         const_cast<vector<double>&>(in_curr_solution.yloc()));
00392    double currHPWL = _db->evalHPWL();
00393    while(currTime > _params->timeCool || budgetTime)
00394    {
00395       brokeFromLoop = false;
00396       iter = 0;
00397 
00398       // ----------------------------------------
00399       // an iteration under the same termperature
00400       // ----------------------------------------
00401       do
00402       {
00403          // ------------------------------------
00404          // special treatment when time is fixed
00405          // ------------------------------------
00406          if (budgetTime)
00407          {
00408             if (count==0)
00409             {
00410                looptm.start(0.0);
00411             }
00412             else if (count==1000)
00413             {  
00414                looptm.stop();               
00415                unit = looptm.getUserTime() / 1000;
00416                if (unit == 0)
00417                {
00418                   unit = 10e-6;
00419                }
00420                seconds -= looptm.getUserTime();
00421                cout << int(seconds/unit) << " moves left with "
00422                     << (unit*1000000) <<" micro seconds per move.\n";
00423                moves = unsigned(seconds/unit/125);// moves every .08 degree
00424             }
00425             else if (count > 1000)
00426             {
00427                seconds -= unit;
00428                if (seconds <= 0)
00429                {
00430                   cout << "TimeOut" << endl;
00431                   return false;
00432                }
00433             }
00434          }
00435          else
00436          {
00437             if (count==0)
00438             {
00439                looptm.start(0.0);
00440             }
00441             else if (count==1000)
00442             {  
00443                looptm.stop();               
00444                unit = looptm.getUserTime() / 1000;
00445                if (unit == 0)
00446                {
00447                   unit = 10e-6;
00448                }
00449                cout << (unit * 1e6) <<" micro seconds per move." << endl;
00450             }
00451          }         
00452          // finish treating time if necessary 
00453 
00454          // -----------------------
00455          // select and apply a move
00456          // -----------------------
00457          
00458          // current solution, "currHPWL" updated only when necessary
00459          double currArea = in_curr_solution.totalArea();
00460          double currHeight = in_curr_solution.totalHeight();
00461          double currWidth = in_curr_solution.totalWidth();
00462          double currAR = currWidth / currHeight;
00463 
00464          ++count; 
00465          ++iter;
00466          prev_move = move;
00467 
00468          // -----select the types of moves here-----
00469          if (_params->softBlocks && currTime < 50)
00470             masterMoveSel = rand() % 1000;
00471          moveSelect = rand() % 1000;
00472 
00473          // -----take action-----
00474          int indexOrient = UNSIGNED_UNINITIALIZED;
00475          parquetfp::ORIENT newOrient = parquetfp::N;
00476          parquetfp::ORIENT oldOrient = parquetfp::N;
00477 
00478          int index = UNINITIALIZED;
00479          double newWidth = UNINITIALIZED;
00480          double newHeight = UNINITIALIZED;
00481 
00482          if(_params->softBlocks && masterMoveSel == 1)
00483             move = packSoftBlocks(2); // needs its return-value (-1)!!!
00484 
00485          else if(_params->softBlocks && masterMoveSel > 950)
00486             move = makeSoftBlMove(index, newWidth, newHeight);
00487          
00488          else if (((reqdAR-currAR)/reqdAR > 0.00005 || 
00489                    (currAR-reqdAR)/reqdAR > 0.00005) && 
00490                   (timeChangeCtr % 4) == 0 && reqdAR != FREE_OUTLINE)
00491          {            
00492             move = makeMove(indexOrient, newOrient, oldOrient);
00493             // move = makeARMove();
00494          }
00495 
00496          else if (false && !minWL &&
00497                   currTime < 30 && (timeChangeCtr % 5) == 0)
00498             move = compactBlocks();
00499          
00500          else if (moveSelect < 150)
00501          {
00502             if (reqdAR != FREE_OUTLINE)
00503                move = makeARMove();
00504             else 
00505                move = makeMove(indexOrient, newOrient, oldOrient);
00506          }
00507          
00508          else if (moveSelect < 300 && minWL)
00509          {
00510             if (reqdAR != FREE_OUTLINE)
00511                move = makeARWLMove();
00512             else
00513                move = makeHPWLMove();
00514          }
00515          
00516          else
00517             move = makeMove(indexOrient, newOrient, oldOrient);
00518 
00519          // -----additional book-keeping for special moves-----
00520          // for orientation moves
00521          if (move == REP_SPEC_ORIENT || move == ORIENT)
00522          {
00523             // temp values
00524             if (minWL)
00525             {
00526                _db->getNodes()->changeOrient(indexOrient, newOrient,
00527                                              *(_db->getNets()));
00528             }
00529          }
00530 
00531          // for soft-block moves
00532          if (move == SOFT_BL)
00533          {
00534             int indexTheta = in_curr_solution.tree[index].orient;
00535             _blockinfo.setBlockDimensions(index,
00536                                           newWidth, newHeight, indexTheta);
00537             in_next_solution.evaluate(in_curr_solution.tree);
00538 
00539             if (minWL)
00540             {
00541                _db->getNodes()->putNodeWidth(index, newWidth);
00542                _db->getNodes()->putNodeHeight(index, newHeight);
00543             }
00544          }            
00545 
00546          // attributes of "in_next_solution"
00547          double tempHeight = in_next_solution.totalHeight(); 
00548          double tempWidth = in_next_solution.totalWidth();  
00549          double tempArea = in_next_solution.totalArea();
00550          double tempAR = tempWidth / tempHeight;
00551          double tempHPWL = UNINITIALIZED;
00552 
00553          // -----------------------------------------------------
00554          // evaulate the temporary solution and calculate "delta"
00555          // -----------------------------------------------------
00556          
00557          double deltaArea = 0;
00558          double deltaHPWL = 0;  
00559          double deltaAR = UNINITIALIZED;
00560          double delta = UNINITIALIZED;
00561  
00562          /* area objective */
00563          if (currTime > 30)
00564             deltaArea = ((tempArea-currArea)*1.2*_params->timeInit) / blocksArea;
00565          else
00566             deltaArea = ((tempArea-currArea)*1.5*_params->timeInit) / blocksArea;
00567          
00568          /* HPWL objective if applicable */ 
00569          if (minWL)
00570          {
00571             _db->updatePlacement(const_cast<vector<double>&>(in_next_solution.xloc()),
00572                                  const_cast<vector<double>&>(in_next_solution.yloc()));
00573             
00574             tempHPWL = _db->evalHPWL();
00575             if(currHPWL == 0)
00576               deltaHPWL = 0;
00577             else
00578             {
00579               if(currTime>30)
00580                deltaHPWL = ((tempHPWL-currHPWL)*1.2*_params->timeInit)/currHPWL; // 1.2
00581               else
00582                deltaHPWL = ((tempHPWL-currHPWL)*1.5*_params->timeInit)/currHPWL; // 1.5 
00583             }
00584          }
00585          
00586          /* AR and overall objective */
00587          delta = deltaArea;
00588          if(reqdAR != FREE_OUTLINE)
00589          {            
00590             deltaAR = ((tempAR - reqdAR)*(tempAR - reqdAR) -
00591                        (currAR - reqdAR)*(currAR - reqdAR)) * 20 * _params->timeInit; // 10 // 1.2
00592             
00593             if(minWL)
00594                delta = (areaWeight * deltaArea +
00595                         wireWeight * deltaHPWL +
00596                         ARWeight * deltaAR);
00597             else
00598                delta = ((areaWeight + wireWeight/2.0) * deltaArea + 
00599                         (ARWeight + wireWeight/2.0) * deltaAR);
00600             
00601          }
00602          else if(minWL)
00603          {
00604             delta = ((areaWeight + ARWeight/2.0)*deltaArea + 
00605                      (wireWeight + ARWeight/2.0)*deltaHPWL);
00606          }
00607          else
00608             delta = deltaArea;
00609          // finish calculating "delta"        
00610 
00611          // --------------------------------------------------
00612          // decide whether a move is accepted based on "delta"
00613          // --------------------------------------------------
00614          
00615          if (delta < 0 || move == MISC)
00616             moveAccepted = true;         
00617          else if (currTime > _params->timeCool) 
00618             // become greedy below time > timeCool
00619          {
00620             double ran = rand() % 10000;
00621             double r = double(ran) / 9999;
00622             if (r < exp(-1*delta/currTime))
00623                moveAccepted = true;
00624             else
00625                moveAccepted = false;
00626          }
00627          else
00628             moveAccepted = false;
00629 
00630          // -----update current solution if accept-----
00631          if (moveAccepted && move != MISC)
00632          {
00633             in_curr_solution = in_next_solution;
00634             currHPWL = tempHPWL;
00635          }
00636 
00637          // -----additional book-keeping for special moves-----
00638          if (move == REP_SPEC_ORIENT || move == ORIENT)
00639          {
00640             // if move not accepted, then put back "oldOrient"
00641             parquetfp::ORIENT actualOrient =
00642                parquetfp::ORIENT(in_curr_solution.tree[indexOrient].orient);
00643             
00644             if (minWL)
00645                _db->getNodes()->changeOrient(indexOrient, actualOrient,
00646                                              *(_db->getNets()));
00647          }
00648 
00649          if (move == SOFT_BL)
00650          {
00651             // if move not accepted, then put back "oldWidth/Height"
00652             double actualWidth = in_curr_solution.width(index);
00653             double actualHeight = in_curr_solution.height(index);
00654             int actualTheta = in_curr_solution.tree[index].orient;
00655             _blockinfo.setBlockDimensions(index,
00656                                           actualWidth, actualHeight,
00657                                           actualTheta);
00658             
00659             if (minWL)
00660             {
00661                _db->getNodes()->putNodeWidth(index, actualWidth);
00662                _db->getNodes()->putNodeHeight(index, actualHeight);
00663             }
00664          }
00665 
00666 //          // update in_best_solution if necessary (doesn't make much diff.)
00667 //          bool updateBest = false;
00668 //          if (_params->reqdAR != FREE_OUTLINE)
00669 //          {
00670 //             if (minWL)
00671 //             {
00672 //                updateBest = (currWidth <= real_reqdWidth &&
00673 //                              currHeight <= real_reqdHeight &&
00674 //                              currHPWL < bestHPWL);
00675 //             }
00676 //             else
00677 //             {
00678 //                updateBest = (currWidth <= real_reqdWidth &&
00679 //                              currHeight <= real_reqdHeight &&
00680 //                              currArea < bestArea);
00681 //             }
00682 //          }
00683 //          else if (minWL)
00684 //          {
00685 //             double currCost =
00686 //                areaWeight * currArea + wireWeight * currHPWL;
00687 //             double bestCost =
00688 //                areaWeight * bestArea + wireWeight * bestHPWL;
00689 
00690 //             updateBest = (currCost < bestCost);
00691 //          }
00692 //          else
00693 //             updateBest = (currArea < bestArea);
00694 
00695 //          if (updateBest)
00696 //             in_best_solution = in_curr_solution;
00697 
00698          // ------------------------------
00699          // special terminating conditions
00700          // ------------------------------
00701          
00702          if (minWL/* && _params->startTime > 100*/)//for lowT anneal don't have this condition
00703          {
00704             // hhchan TODO:  clean-up this code mess 
00705             if(currArea <= real_reqdArea && currHeight <= real_reqdHeight && 
00706                currWidth <= real_reqdWidth && reqdAR != FREE_OUTLINE && currTime < 5)
00707                return true;
00708 
00709             if (reqdAR != FREE_OUTLINE && currTime < 5 && 
00710                 _params->dontClusterMacros && _params->solveTop)
00711             {
00712                double widthWMacroOnly = _db->getXSizeWMacroOnly();
00713                double heightWMacroOnly = _db->getYSizeWMacroOnly();
00714 
00715                if (widthWMacroOnly <= real_reqdWidth &&
00716                    heightWMacroOnly <= real_reqdHeight)
00717                   return true;
00718             }
00719          }
00720          else
00721          {
00722             if(currArea <= real_reqdArea && currHeight <= real_reqdHeight && 
00723                currWidth <= real_reqdWidth && reqdAR != FREE_OUTLINE)
00724                return true;
00725          }
00726           
00727          if (iter >= moves)
00728             break;
00729 
00730 #ifdef PARQUET_DEBUG_HAYWARD_ASSERT_BTREEANNEAL
00731          // -----debugging messages-----
00732          for (int i = 0; i < in_curr_solution.NUM_BLOCKS; i++)
00733          {
00734             if (minWL && (int(in_curr_solution.tree[i].orient) !=
00735                           int(_db->getNodes()->getNode(i).getOrient())))
00736             {
00737                cout << "round [" << count << "]: orient of block[" << i << "] is not consistent" << endl;
00738                printf("in_curr_solution:orient %d vs. _db->orient: %d, move: %d",
00739                       int(in_curr_solution.tree[i].orient),
00740                       int(_db->getNodes()->getNode(i).getOrient()), move);
00741                cin.get();
00742             }
00743 
00744             int theta = in_curr_solution.tree[i].orient;
00745             if (theta != int(_physicalOrient[i][theta]))
00746             {
00747                printf("round[%d]: orient of block[%d] is not consistent, in_curr_soln: %d vs phyOrient: %d move: %d\n",
00748                       count, i, theta, _physicalOrient[i][theta], move);
00749                cin.get();
00750             }
00751             
00752             if (fabs(in_curr_solution.width(i) - blockinfo.currDimensions[i].width[theta]) > 1e-6)
00753             {
00754                printf("round[%d]: width of block[%d] is not consistent.  in_curr_soln: %.2f vs. blockinfo: %.2f move: %d prevMove: %d\n",
00755                       count, i, in_curr_solution.width(i), blockinfo.currDimensions[i].width[theta], move, prev_move);
00756                printf("round[%d]: oldWidth: %.2f oldHeight: %.2f newWidth: %.2f newHeight: %.2f moveAccepted: %s\n",
00757                       count, -1.0, -1.0, newWidth, newHeight, (moveAccepted)? "T" : "F");
00758                cin.get();
00759             }
00760 
00761             if (fabs(in_curr_solution.height(i) - blockinfo.currDimensions[i].height[theta]) > 1e-6)
00762             {
00763                printf("round[%d]: height of block[%d] is not consistent.  in_curr_soln: %.2f vs. blockinfo: %.2f move: %d prevMove: %d\n",
00764                       count, i, in_curr_solution.height(i), blockinfo.currDimensions[i].height[theta], move, prev_move);
00765                printf("round[%d]: oldWidth: %.2f oldHeight: %.2f newWidth: %.2f newHeight: %.2f moveAccepted: %s\n",
00766                       count, -1.0, -1.0, newWidth, newHeight, (moveAccepted)? "T" : "F");
00767                cin.get();
00768             }
00769 
00770             if (minWL && fabs(in_curr_solution.width(i) - _db->getNodes()->getNodeWidth(i)) > 1e-6)
00771             {
00772                printf("round[%d]: width of block[%d] is not consistent.  in_curr_solution: %.2f vs._db: %.2f move: %d\n",
00773                       count, i, in_curr_solution.width(i), _db->getNodes()->getNodeWidth(i), move);
00774                cin.get();
00775             }
00776 
00777             if (in_curr_solution.width(i) < 1e-10 ||
00778                 in_curr_solution.height(i) < 1e-10)
00779             {
00780                printf("round[%d]: width of block[%d]: %f height: %f move: %d\n",
00781                       count, i, in_curr_solution.width(i), in_curr_solution.height(i), move);
00782                cin.get();
00783             }
00784          }
00785          // -----end of debugging messages-----
00786 #endif         
00787       }
00788       while (iter < 4*size || budgetTime);
00789       // finish the loop under constant temperature
00790 
00791       // -----------------------------
00792       // update temperature "currTime"
00793       // -----------------------------
00794       
00795       double alpha = UNINITIALIZED;
00796       ++timeChangeCtr;
00797       if (budgetTime)
00798       {
00799          percent = seconds/total;
00800         
00801          if (percent < 0.66666 && percent > 0.33333)
00802             alpha = 0.9;
00803          else if (percent < 0.33333 && percent > 0.16666)
00804             alpha = 0.95;
00805          else if (percent < 0.16666 && percent > 0.06666)
00806             alpha = 0.96;
00807          else if(percent <.06666 && percent >.00333)
00808             alpha = 0.8;
00809          else if(percent <.00333 && percent >.00003)
00810             alpha = 0.98;
00811          else
00812             alpha = 0.85;
00813       }
00814       else
00815       {
00816          if (currTime < 2000 && currTime > 1000)
00817             alpha = 0.9;
00818          else if (currTime < 1000 && currTime > 500)
00819             alpha = 0.95;
00820          else if (currTime < 500 && currTime > 200)
00821             alpha = 0.96;
00822          else if (currTime < 200 && currTime > 10)
00823             alpha = 0.96;
00824          else if (currTime < 15 && currTime > 0.1)
00825             alpha = 0.98;
00826          else
00827             alpha = 0.85;
00828       }
00829       currTime *= alpha;
00830       
00831       if (brokeFromLoop)
00832          break;
00833    }
00834 
00835    cout << "NumMoves attempted: " << count << endl;
00836    if (reqdAR != FREE_OUTLINE)
00837       return false;
00838    else
00839       return true;
00840 }
00841 // --------------------------------------------------------
00842 void BTreeAreaWireAnnealer::takePlfromDB()
00843 {
00844    Pl2BTree converter(_db->getXLocs(),
00845                       _db->getYLocs(),
00846                       _db->getNodeWidths(),
00847                       _db->getNodeHeights(),
00848                       Pl2BTree::TCG);
00849    in_curr_solution.evaluate(converter.btree());
00850    in_next_solution = in_curr_solution;
00851 }
00852 // --------------------------------------------------------
00853 void BTreeAreaWireAnnealer::compactSoln()
00854 {
00855    BTreeCompactor compactor(in_curr_solution);
00856 
00857    int round = 0;
00858    int numBlkChange = compactor.compact();
00859    double lastArea = in_curr_solution.totalArea();
00860    double currArea = compactor.totalArea();
00861    while (numBlkChange > 0)
00862    {
00863       printf("round[%d] %d blks moved, area: %.2f -> %.2f\n",
00864              round, numBlkChange, lastArea, currArea);
00865 
00866       numBlkChange = compactor.compact();
00867       round++;
00868       lastArea = currArea;
00869       currArea = compactor.totalArea();
00870    }
00871    printf("round[%d] %d blks moved, area: %.2f -> %.2f\n",
00872           round, numBlkChange, lastArea, currArea);
00873 
00874    in_curr_solution = compactor;
00875    DBfromSoln(in_curr_solution);
00876 }
00877 // --------------------------------------------------------
00878 int BTreeAreaWireAnnealer::makeMove(int& indexOrient,
00879                                     parquetfp::ORIENT& newOrient,
00880                                     parquetfp::ORIENT& oldOrient)
00881 {
00882    BTree::MoveType move = get_move();
00883    indexOrient = UNSIGNED_UNINITIALIZED;
00884    newOrient = parquetfp::N;
00885    oldOrient = parquetfp::N;
00886    switch(move)
00887    {
00888    case BTree::SWAP:
00889       perform_swap();
00890       return 1;
00891 
00892    case BTree::ROTATE:
00893       perform_rotate(indexOrient, newOrient, oldOrient);
00894       return int(REP_SPEC_ORIENT);
00895 
00896    case BTree::MOVE:
00897       perform_move();
00898       return 3;
00899 
00900    default:
00901       cout << "ERROR: invalid move specified in makeMove()" << endl;
00902       exit(1);
00903    }
00904    return MISC;
00905 }
00906 // --------------------------------------------------------
00907 int BTreeAreaWireAnnealer::makeMoveSlacks()
00908 {
00909    int movedir = rand() % 100;
00910    int threshold = 50;
00911    bool horizontal = (movedir < threshold);
00912 
00913    makeMoveSlacksCore(horizontal);
00914 
00915    static int total = 0;
00916    static int numHoriz = 0;
00917 
00918    total++;
00919    numHoriz += ((horizontal)? 1 : 0);
00920 
00921    if (total % 1000 == 0)
00922       cout << "total: " << total << "horiz: " << numHoriz << endl;
00923    return SLACKS_MOVE;
00924 }
00925 // --------------------------------------------------------
00926 int BTreeAreaWireAnnealer::makeARMove()
00927 {
00928    double currWidth = in_curr_solution.totalWidth();
00929    double currHeight = in_curr_solution.totalHeight();
00930    double currAR = currWidth / currHeight;
00931 
00932    const double reqdAR = _params->reqdAR;
00933    bool horizontal = currAR > reqdAR;
00934 
00935    makeMoveSlacksCore(horizontal);
00936    return AR_MOVE;
00937 }
00938 // --------------------------------------------------------
00939 void BTreeAreaWireAnnealer::makeMoveSlacksCore(bool horizontal)
00940 {
00941    _slackEval->evaluateSlacks(in_curr_solution);
00942    
00943    vector<int> indices_sorted;
00944    const vector<double>& slacks = (horizontal)?
00945       _slackEval->xSlack() : _slackEval->ySlack();
00946    
00947    sort_slacks(slacks, indices_sorted);
00948 
00949    int blocknum = in_curr_solution.NUM_BLOCKS;
00950    int range = int(ceil(blocknum / 5.0));
00951    
00952    int operand_ptr = rand() % range;
00953    int operand = indices_sorted[operand_ptr];
00954    while (operand_ptr > 0 && slacks[operand] > 0)
00955    {
00956       operand_ptr--;
00957       operand = indices_sorted[operand_ptr];
00958    }
00959    
00960    int target_ptr = blocknum - 1 - (rand() % range);
00961    int target = indices_sorted[target_ptr];
00962    while (target_ptr < (blocknum-1) && slacks[target] == 0)
00963    {
00964       target_ptr++;
00965       target = indices_sorted[target_ptr];
00966    }
00967 
00968    in_next_solution = in_curr_solution;
00969    in_next_solution.move(operand, target, horizontal);
00970 }
00971 // --------------------------------------------------------
00972 int BTreeAreaWireAnnealer::makeHPWLMove()
00973 {
00974    int size = in_curr_solution.NUM_BLOCKS;
00975    int operand = rand() % size;
00976    int target = UNSIGNED_UNINITIALIZED;
00977 
00978    vector<int> searchBlocks;
00979    locateSearchBlocks(operand, searchBlocks);
00980    
00981    if (searchBlocks.size() > 0)
00982    {
00983       int temp = rand() % searchBlocks.size();
00984       target = searchBlocks[temp];
00985    }
00986    else
00987    {
00988       do
00989          target = rand() % size;
00990       while(target == operand);
00991    }
00992 
00993    bool leftChild = bool(rand() % 2);
00994    in_next_solution = in_curr_solution;
00995    in_next_solution.move(operand, target, leftChild);
00996    return HPWL;
00997 }
00998 // --------------------------------------------------------
00999 int BTreeAreaWireAnnealer::makeARWLMove()
01000 {
01001    _slackEval->evaluateSlacks(in_curr_solution);
01002 
01003    const double reqdAR = _params->reqdAR;
01004    const double currAR =
01005       in_curr_solution.totalWidth() / in_curr_solution.totalHeight();
01006    const bool horizontal = currAR > reqdAR;
01007    const vector<double>& slacks = (horizontal)?
01008       _slackEval->xSlack() : _slackEval->ySlack(); 
01009    
01010    vector<int> indices_sorted;
01011    sort_slacks(slacks, indices_sorted);
01012    
01013    int blocknum = in_curr_solution.NUM_BLOCKS;
01014    int range = int(ceil(blocknum / 5.0));
01015    
01016    int operand_ptr = rand() % range;
01017    int operand = indices_sorted[operand_ptr];
01018    while (operand_ptr > 0 && slacks[operand] > 0)
01019    {
01020       operand_ptr--;
01021       operand = indices_sorted[operand_ptr];
01022    }
01023 
01024    vector<int> searchBlocks;
01025    locateSearchBlocks(operand, searchBlocks);
01026 
01027    int target = UNSIGNED_UNINITIALIZED;
01028    double maxSlack = -1;
01029    if (searchBlocks.size() == 0)
01030    {
01031       do
01032          target = rand() % blocknum;
01033       while(target == operand);
01034    }
01035    else
01036    {
01037       for (unsigned int i = 0; i < searchBlocks.size(); i++)
01038       {
01039          int thisBlk = searchBlocks[i];
01040          if (slacks[thisBlk] > maxSlack)
01041          {
01042             maxSlack = slacks[thisBlk];
01043             target = thisBlk;
01044          }
01045       }
01046    }
01047 
01048    in_next_solution = in_curr_solution;
01049    in_curr_solution.move(operand, target, horizontal);
01050    return ARWL; 
01051 }
01052 // --------------------------------------------------------
01053 int BTreeAreaWireAnnealer::makeSoftBlMove(int& index,
01054                                           double& newWidth,
01055                                           double& newHeight)
01056 {
01057    static const int NOT_FOUND = NOT_FOUND;
01058    _slackEval->evaluateSlacks(in_curr_solution);
01059    
01060    int moveDir = rand() % 2;
01061    bool horizontal = (moveDir%2 == 0);
01062    index = getSoftBlIndex(horizontal);
01063 
01064    if (index == NOT_FOUND)
01065       index = getSoftBlIndex(!horizontal);
01066 
01067    if (index != NOT_FOUND)
01068    {
01069       return getSoftBlNewDimensions(index, newWidth, newHeight);
01070    }
01071    else
01072    {
01073       newWidth = NOT_FOUND;
01074       newHeight = NOT_FOUND;
01075       return MISC;
01076    }
01077 }
01078 // --------------------------------------------------------
01079 int BTreeAreaWireAnnealer::getSoftBlIndex(bool horizontal) const
01080 {
01081    static const int NOT_FOUND = NOT_FOUND;
01082    const int blocknum = in_curr_solution.NUM_BLOCKS;
01083    const vector<double>& slacks = (horizontal)?
01084       _slackEval->xSlack() : _slackEval->ySlack();
01085 
01086    const vector<double>& orth_slacks = (horizontal)?
01087       _slackEval->ySlack() : _slackEval->xSlack();
01088 
01089    vector<int> indices_sorted;
01090    sort_slacks(slacks, indices_sorted);
01091 
01092    int operand = NOT_FOUND; // "-1" stands for not found
01093    for (int i = 0; (i < blocknum) && (operand == NOT_FOUND); i++)
01094    {
01095       int index = indices_sorted[i];
01096       if (blockinfo.blockARinfo[index].isSoft)
01097       {
01098          int theta = in_curr_solution.tree[index].orient;
01099          double minAR = blockinfo.blockARinfo[index].minAR[theta];
01100          double maxAR = blockinfo.blockARinfo[index].maxAR[theta];
01101          
01102          double currWidth = in_curr_solution.width(index);
01103          double currHeight = in_curr_solution.height(index);
01104          double currAR = currWidth / currHeight;
01105 
01106          bool adjustable = (horizontal)?
01107             (currAR > minAR) : (currAR < maxAR);
01108 
01109          if (orth_slacks[index] > 0 && adjustable)
01110             operand = index;
01111       }
01112    }
01113    return operand;
01114 }   
01115 // --------------------------------------------------------
01116 int BTreeAreaWireAnnealer::getSoftBlNewDimensions(int index,
01117                                                   double& newWidth,
01118                                                   double& newHeight) const
01119 {
01120    if (blockinfo.blockARinfo[index].isSoft)
01121    {
01122       double origWidth = in_curr_solution.width(index);
01123       double origHeight = in_curr_solution.height(index);
01124       double indexArea = blockinfo.blockARinfo[index].area;
01125       
01126       int theta = in_curr_solution.tree[index].orient;
01127       double minAR = blockinfo.blockARinfo[index].minAR[theta];
01128       double maxAR = blockinfo.blockARinfo[index].maxAR[theta];
01129       
01130       double maxWidth = sqrt(indexArea * maxAR);
01131       double maxHeight = sqrt(indexArea / minAR);
01132       
01133       double indexSlackX = _slackEval->xSlack()[index];
01134       double indexSlackY = _slackEval->ySlack()[index];
01135       if (indexSlackX > indexSlackY)
01136       {
01137          newWidth = min(origWidth+indexSlackX, maxWidth);
01138          newHeight = indexArea / newWidth;
01139       }
01140       else
01141       {
01142          newHeight = min(origHeight+indexSlackY, maxHeight);
01143          newWidth = indexArea / newHeight;
01144       }
01145       return SOFT_BL;
01146    }
01147    else
01148       return NOOP;
01149 }
01150 // --------------------------------------------------------
01151 int BTreeAreaWireAnnealer::packSoftBlocks(int numIter)
01152 {
01153    const int NUM_BLOCKS = in_curr_solution.NUM_BLOCKS;
01154    for (int iter = 0; iter < numIter; iter++)
01155    {
01156       bool horizontal = (iter % 2 == 0);
01157       _slackEval->evaluateSlacks(in_curr_solution);
01158 
01159       const vector<double>& slacks = (horizontal)?
01160          _slackEval->xSlack() : _slackEval->ySlack();
01161 
01162       vector<int> indices_sorted;
01163       sort_slacks(slacks, indices_sorted);
01164       for (int i = 0; i < NUM_BLOCKS; i++)
01165       {
01166          int index = indices_sorted[i];
01167          double origWidth = in_curr_solution.width(index);
01168          double origHeight = in_curr_solution.height(index);
01169 
01170          double newWidth, newHeight;
01171          int softDecision = makeIndexSoftBlMove(index, newWidth, newHeight);
01172 
01173          if (softDecision == SOFT_BL)
01174          {
01175             // change dimensions only when needed
01176             int theta = in_curr_solution.tree[index].orient;
01177             _blockinfo.setBlockDimensions(index, newWidth, newHeight, theta);
01178 
01179             in_next_solution.evaluate(in_curr_solution.tree);
01180 
01181             double origTotalArea = in_curr_solution.totalArea();
01182             double newTotalArea = in_next_solution.totalArea();
01183             if (newTotalArea < origTotalArea)
01184             {
01185                in_curr_solution = in_next_solution;
01186                if (_params->minWL)
01187                {
01188                   _db->getNodes()->putNodeWidth(index, newWidth);
01189                   _db->getNodes()->putNodeHeight(index, newHeight);
01190                }
01191             }
01192             else
01193             {
01194                _blockinfo.setBlockDimensions(index, origWidth, origHeight, theta);
01195             }
01196          }
01197       }
01198    }
01199    return MISC;
01200 }
01201 // --------------------------------------------------------
01202 void BTreeAreaWireAnnealer::locateSearchBlocks(int operand,
01203                                                vector<int>& searchBlocks)
01204 {
01205    int size = in_curr_solution.NUM_BLOCKS;
01206    vector<bool> seenBlocks(size, false);
01207    seenBlocks[operand] = true;
01208    double unitRadiusSize = max(in_curr_solution.totalWidth(),
01209                                in_curr_solution.totalHeight());
01210    unitRadiusSize /= sqrt(double(size));
01211 
01212    vector<double>& xloc = const_cast<vector<double>&>(in_curr_solution.xloc());
01213    vector<double>& yloc = const_cast<vector<double>&>(in_curr_solution.yloc());
01214    parquetfp::Point idealLoc(_analSolve->getOptLoc(operand, xloc, yloc));
01215    // get optimum location of "operand"
01216 
01217    int searchRadiusNum = int(ceil(size / 5.0));
01218    double searchRadius = 0;
01219    for(int i = 0; ((i < searchRadiusNum) &&
01220                    (searchBlocks.size() < unsigned(searchRadiusNum))); ++i)
01221    {
01222       searchRadius += unitRadiusSize;
01223       for(int j = 0; ((j < size) &&
01224                       (searchBlocks.size() < unsigned(searchRadiusNum))); ++j)
01225       {
01226          if (!seenBlocks[j])
01227          {
01228             double xDist = xloc[j] - idealLoc.x;
01229             double yDist = yloc[j] - idealLoc.y;
01230             double distance = sqrt(xDist*xDist + yDist*yDist);
01231             if(distance < searchRadius)
01232             {
01233                seenBlocks[j] = true; 
01234                searchBlocks.push_back(j);
01235             }
01236          }
01237       }
01238    }
01239 }
01240 // --------------------------------------------------------
01241 void BTreeAreaWireAnnealer::GenerateRandomSoln(BTree& soln,
01242                                                int blocknum) const
01243 {
01244    vector<int> tree_bits;
01245    int balance = 0;
01246    int num_zeros = 0;
01247    for (int i = 0; i < 2*blocknum; i++)
01248    {
01249       bool assigned = false;
01250       double rand_num = double(rand()) / (RAND_MAX+1.0);
01251       double threshold;
01252 
01253       if (balance == 0)
01254          threshold = 1; // push_back "0" for sure
01255       else if (num_zeros == blocknum) 
01256          threshold = 0; // push_back "1" for sure
01257       else
01258          threshold = 1; // (rand_num * (balance - rand_num));
01259          
01260       if (rand_num >= threshold)
01261       {
01262          tree_bits.push_back(1);
01263          balance--;
01264          assigned = true;
01265       }
01266       else
01267       {
01268          tree_bits.push_back(0);
01269          balance++;
01270          num_zeros++;
01271          assigned = true;
01272       }
01273    }
01274    
01275    vector<int> tree_perm;
01276    tree_perm.resize(blocknum);
01277    for (int i = 0; i < blocknum; i++)
01278       tree_perm[i] = i;
01279    random_shuffle(tree_perm.begin(), tree_perm.end());
01280 
01281    vector<int> tree_perm_inverse(blocknum);
01282    for (int i = 0; i < blocknum; i++)
01283       tree_perm_inverse[tree_perm[i]] = i;
01284 
01285    vector<int> tree_orient(blocknum);
01286    for (int i = 0; i < blocknum; i++)
01287    {
01288       int rand_num = int(8 * (double(rand()) / (RAND_MAX + 1.0)));
01289       rand_num = _physicalOrient[i][rand_num];
01290 
01291       tree_orient[tree_perm_inverse[i]] = rand_num;
01292    }
01293 
01294    soln.evaluate(tree_bits, tree_perm, tree_orient);
01295 }
01296 // --------------------------------------------------------

Generated on Mon Apr 25 01:09:24 2005 for Parquete by doxygen 1.3.2