VIS

src/ord/ordPerm.c

Go to the documentation of this file.
00001 
00032 #include "ordInt.h"
00033 
00034 static char rcsid[] UNUSED = "$Id: ordPerm.c,v 1.9 2005/04/16 06:15:25 fabio Exp $";
00035 
00036 /*---------------------------------------------------------------------------*/
00037 /* Structure declarations                                                     */
00038 /*---------------------------------------------------------------------------*/
00039 
00040 typedef struct proc_pair {
00041     long proc_no;
00042     long var_no;
00043 } pair;
00044 
00045 typedef struct proc_struct {
00046   int num_loc_vars;
00047   array_t *o_list; /* of pair */
00048   array_t *i_list; /* of pair */
00049 } proc_struct;  
00050 
00051 typedef struct Proc_Com_Graph {
00052     int          num_vars;
00053     int          num_proc;
00054     int         *width_list;
00055     proc_struct *proc_list;
00056     int         *locations;      /* Array of length num_proc used as temporary storage by some
00057                                     functions */
00058     int         *variables;      /* Array of length num_vars used as temporary storage by some
00059                                     functions */
00060     
00061 } Proc_Com_Graph;
00062 
00063 
00064 /*---------------------------------------------------------------------------*/
00065 /* Variable declarations                                                     */
00066 /*---------------------------------------------------------------------------*/
00081 static int number_of_calls;
00082 
00083 
00084 /*---------------------------------------------------------------------------*/
00085 /* Macro declarations                                                        */
00086 /*---------------------------------------------------------------------------*/
00087 
00088 
00091 /*---------------------------------------------------------------------------*/
00092 /* Static function prototypes                                                */
00093 /*---------------------------------------------------------------------------*/
00094 
00095 static lsList NetworkComputeLatchOrder(Ntk_Network_t * network, int verbose);
00096 static int * LatchPermutationCompute(Proc_Com_Graph *PCG, int choice, int verbose);
00097 static double rev_fac(int num_rev_bits);
00098 static double cost_for_cut(Proc_Com_Graph * PCG, int * perm, int end_of_set1);
00099 static void append_best(int * opt_perm, int loc, Proc_Com_Graph * PCG);
00100 static double cost_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
00101 static long int cost_touati_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
00102 static void swap(int * opt_perm, int i, int j);
00103 static void append_best_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
00104 static void append_touati_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
00105 static void init_heur(Proc_Com_Graph * PCG, int * opt_perm);
00106 static void heur_2(Proc_Com_Graph * PCG, int * opt_perm);
00107 static void heur_touati_la2(Proc_Com_Graph * PCG, int * opt_perm);
00108 static int * opt_proc_order(Proc_Com_Graph * PCG);
00109 static int * opt_touati_order(Proc_Com_Graph * PCG);
00110 static double cost_total(Proc_Com_Graph * PCG, int * perm);
00111 static int * random_permutation(int seed, int n_elts);
00112 
00116 /*---------------------------------------------------------------------------*/
00117 /* Definition of exported functions                                          */
00118 /*---------------------------------------------------------------------------*/
00119 
00120 
00121 /*---------------------------------------------------------------------------*/
00122 /* Definition of internal functions                                          */
00123 /*---------------------------------------------------------------------------*/
00124 
00141 lsList
00142 OrdNetworkOrderRootsByPerm(
00143   Ntk_Network_t *network,
00144   int verbose)
00145 {
00146   lsGen gen;
00147   Ntk_Node_t *node;
00148   lsList dataInputs;
00149   st_table *processedTable = st_init_table(st_ptrcmp, st_ptrhash);
00150   lsList otherCombOuts = lsCreate();
00151 
00152   /*
00153    * Create a list of all combinational outputs that are not data inputs to
00154    * latches. A node can drive more than one latch data input, latch initial
00155    * input, or primary output. Use a hash table to ensure that no node appears
00156    * twice in the list.
00157    */
00158   Ntk_NetworkForEachCombOutput(network, gen, node) {
00159     if (!Ntk_NodeTestIsLatchDataInput(node)) {
00160       OrdNodeAddToList(otherCombOuts, processedTable, node);
00161     }
00162   }
00163   st_free_table(processedTable);
00164 
00165   /* Compute depth of all roots in otherCombOuts. */
00166   OrdNetworkComputeNodeDepths(network, otherCombOuts);
00167 
00168   /* Sort otherCombOuts based on depth. */
00169   lsSort(otherCombOuts, OrdNodesFromListCompareDepth);
00170 
00171   /* Compute order on dataInputs roots using the permutation method. */
00172   dataInputs = NetworkComputeLatchOrder(network, verbose);
00173 
00174   /* Add the otherCombOuts list to the end of the dataInputs list. */
00175   Ord_ListAppendList(dataInputs, otherCombOuts);
00176   (void) lsDestroy(otherCombOuts, (void (*) (lsGeneric)) NULL);
00177   
00178   return dataInputs;
00179 }
00180 
00181 
00182 /*---------------------------------------------------------------------------*/
00183 /* Definition of static functions                                            */
00184 /*---------------------------------------------------------------------------*/
00185 
00200 static lsList
00201 NetworkComputeLatchOrder(
00202   Ntk_Network_t * network,
00203   int verbose)
00204 {
00205   int           i, j;
00206   lsGen         listGen;
00207   st_generator *stGen;
00208   Ntk_Node_t   *latch;
00209   lsList        tfoLatchList;
00210   int          *latchOrderArray;
00211   long          count             = 0L;
00212   st_table     *idToLatch         = st_init_table(st_numcmp, st_numhash);
00213   int           numLatches        = Ntk_NetworkReadNumLatches(network);
00214   st_table     *latchDependencies = Ntk_NetworkComputeLatchDependencies(network);
00215   lsList        latchOrderList    = lsCreate();
00216   int           latchOrderingMode = 1;  /* FIX: make an option */
00217   double        convConstant      = log10(2.0);
00218   Proc_Com_Graph *PCG;
00219   pair         *cur_pair;
00220   
00221   /*
00222    * Assign unique integer between 0 and numLatches-1 to each latch.  Store
00223    * this correspondance in the idToLatch hash table.
00224    * (NOTE: may be sensitive to ordering in memory.)
00225    */
00226   Ntk_NetworkForEachLatch(network, listGen, latch) {
00227     Ntk_NodeSetUndef(latch, (void *) count);
00228     st_insert(idToLatch, (char *) count, (char *) latch);
00229     count++;
00230   }
00231 
00232   /* Create a Proc_Com_Graph and write the communications
00233    * structure of the network into it
00234    */
00235   
00236   PCG = ALLOC(Proc_Com_Graph, 1);
00237   PCG->num_proc = numLatches; /*  SER (void) fprintf(pcgFile, "%d\n", numLatches);  */
00238   PCG->num_vars = numLatches; /*  SER (void) fprintf(pcgFile, "%d\n", numLatches);  */
00239 
00240   PCG->proc_list = ALLOC(proc_struct, PCG->num_proc);
00241   PCG->width_list= ALLOC(int, PCG->num_vars);
00242   PCG->locations = ALLOC(int, PCG->num_proc);  
00243   PCG->variables = ALLOC(int, PCG->num_vars);
00244 
00245   for(i=0;i< PCG->num_proc ; i++) {
00246       PCG->proc_list[i].o_list= array_alloc(pair *, 0);
00247       PCG->proc_list[i].i_list= array_alloc(pair *, 0);
00248   };
00249 
00250   /*
00251    * For each latch/tfoLatchList pair, write information about the latch, and
00252    * write the latches to which the latch fanouts. Finish the entry with "%%".
00253    * Here is the general format for a process:
00254    * process # list of local vars to process #
00255    *     fanout-latch : local-var-fanning-to  width-of-local-var /
00256    *       ....
00257    *     fanout-latch : local-var-fanning-to  width-of-local-var / %%
00258    *
00259    * When this format is specialized to case where each process is a single
00260    * latch, then the format looks like:
00261    * latch # latch #
00262    *     fanout-latch : latch  width-of-latch /
00263    *       ....
00264    *     fanout-latch : latch  width-of-latch / %%
00265    */
00266   st_foreach_item(latchDependencies, stGen, &latch, &tfoLatchList) {
00267     Ntk_Node_t *tfoLatch;
00268     int         varWidth;
00269     long        var_no, fr_no, to_no;
00270     
00271 
00272     /*
00273      * Write the latch id and the cardinality of the latch variable
00274      * domain.
00275      */
00276     fr_no =  (long) Ntk_NodeReadUndef(latch);
00277     PCG->proc_list[fr_no].num_loc_vars = 1;
00278     
00279     
00280     /*
00281      * For each transitive fanout latch, write the tfoLatch id, the latch
00282      * id, and the width of the latch variable (assumes minimum
00283      * encoding). Width is ceiling(log2(number of values in domain)).
00284      */
00285     varWidth = (int) ceil(log10
00286              ((double)Var_VariableReadNumValues(Ntk_NodeReadVariable(latch)))
00287                           / convConstant);
00288     lsForEachItem(tfoLatchList, listGen, tfoLatch) {
00289         to_no = (long) Ntk_NodeReadUndef(tfoLatch);
00290         var_no = (long) Ntk_NodeReadUndef(latch);
00291 
00292         cur_pair = ALLOC(pair,1);
00293         cur_pair->proc_no = to_no;
00294         cur_pair->var_no = var_no;
00295         array_insert_last(pair *, PCG->proc_list[fr_no].o_list, cur_pair);
00296 
00297         cur_pair = ALLOC(pair,1);
00298         cur_pair->proc_no = fr_no;
00299         cur_pair->var_no = var_no;         
00300         array_insert_last(pair *, PCG->proc_list[to_no].i_list, cur_pair);
00301         
00302         PCG->width_list[var_no] = varWidth;
00303     }
00304   }
00305 
00306   /*
00307    * We don't need the latchDependencies table anymore.  Free the list stored
00308    * at each value, and then free the table itself.
00309    */
00310   st_foreach_item(latchDependencies, stGen, &latch, &tfoLatchList) {
00311     (void) lsDestroy(tfoLatchList, (void (*) (lsGeneric)) NULL);
00312   }
00313   st_free_table(latchDependencies);
00314 
00315   /*
00316    * Compute the order on the latches. This is returned as an array of
00317    * integers, where the latch whose id is latchOrderArray[i] is ordered in
00318    * the ith position of latchOrderList. Note that the returned list actually
00319    * contains the latch data inputs, not the latches themselves.
00320    */
00321   latchOrderArray = LatchPermutationCompute(PCG, latchOrderingMode, verbose);
00322   
00323   for (i=0; i < PCG->num_proc; i++) {
00324       for (j=0; j<array_n(PCG->proc_list[i].o_list); j++) {
00325               cur_pair = array_fetch(pair *, PCG->proc_list[i].o_list, j);
00326               FREE(cur_pair);
00327       }
00328 
00329       for (j=0; j<array_n(PCG->proc_list[i].i_list); j++) {
00330               cur_pair = array_fetch(pair *, PCG->proc_list[i].i_list, j);
00331               FREE(cur_pair);
00332       }
00333       
00334       array_free(PCG->proc_list[i].o_list);
00335       array_free(PCG->proc_list[i].i_list);
00336   }
00337 
00338   FREE(PCG->proc_list);
00339   FREE(PCG->width_list);
00340   FREE(PCG->variables);
00341   FREE(PCG->locations);
00342   FREE(PCG);
00343   
00344   for (i = 0; i < numLatches; i++) {
00345     int status UNUSED = st_lookup(idToLatch,
00346                                   (char *) (long) (latchOrderArray[i]),
00347                                   &latch);
00348     assert(status);
00349     (void) lsNewEnd(latchOrderList, (lsGeneric) Ntk_LatchReadDataInput(latch), LS_NH);
00350   }
00351 
00352   /*
00353    * We are done with idToLatch and latchOrderArray.
00354    */
00355   st_free_table(idToLatch);
00356   FREE(latchOrderArray); 
00357   
00358   return (latchOrderList);
00359 }
00360 
00361 
00373 static int *
00374 LatchPermutationCompute(
00375   Proc_Com_Graph *PCG,
00376   int choice,
00377   int verbose)
00378 {
00379   int *opt_perm;
00380 
00381   if (choice == 0) {      
00382       opt_perm = opt_proc_order(PCG);
00383   }
00384   else if (choice == 1) {
00385     opt_perm = ALLOC(int, PCG->num_proc);
00386     init_heur(PCG, opt_perm);
00387   }
00388   else if (choice == 2) {
00389     opt_perm = opt_touati_order(PCG);
00390   }
00391   else if (choice == 3) {
00392     opt_perm = random_permutation(7,PCG->num_vars);
00393   }
00394   else {
00395     fail("Unknown Option for Computing Latch Permutation");
00396   }
00397 
00398   if (verbose > 1) {
00399     (void) fprintf(vis_stdout, "TOTAL COST= %e \n",cost_total(PCG,opt_perm));
00400   }
00401   
00402   return opt_perm;
00403 }
00404 
00405 
00417 static double
00418 rev_fac(
00419   int  num_rev_bits)
00420 {
00421   double result;
00422   
00423   result  = pow( ((double) 2.0),((double) num_rev_bits) );
00424  
00425   return result; 
00426 }
00427 
00428 
00441 static double
00442 cost_for_cut(
00443   Proc_Com_Graph * PCG,
00444   int * perm,
00445   int  end_of_set1)
00446 {
00447   int i, j;
00448   double result; 
00449   int forw  = 0,  rev = 0; 
00450   pair *cur_pair;
00451   
00452   for (i=0; i<=end_of_set1; i++) {
00453     PCG->locations[perm[i]]=1;
00454   }
00455         
00456   for (i=end_of_set1+1; i<PCG->num_proc; i++) {
00457     PCG->locations[perm[i]]=2;
00458   }
00459 
00460   for (i=0; i<PCG->num_vars; i++) {
00461     PCG->variables[i]=0;
00462   }
00463         
00464   /* Count the # of   forward crossing  bits   */
00465 /*  for (i=0; i<=end_of_set1; i++) {
00466     st_foreach_item(PCG->proc_list[perm[i]].o_list, 
00467                     gen,(char **)&bit_no,(char **)&to_proc) {  
00468       if (PCG->locations[to_proc] ==2)  {
00469         PCG->variables[bit_no]++ ;
00470       }
00471     }
00472   }
00473 */
00474   for (i=0; i<=end_of_set1; i++) 
00475       for (j=0; j<array_n(PCG->proc_list[perm[i]].o_list); j++) {
00476           cur_pair = array_fetch(pair *, PCG->proc_list[perm[i]].o_list, j);
00477           if (PCG->locations[cur_pair->proc_no] ==2)  {
00478               PCG->variables[cur_pair->var_no]++ ;
00479           }      
00480       }
00481   
00482   
00483   for (i=0; i<PCG->num_vars; i++) {
00484     if (PCG->variables[i] > 0) {
00485       ++forw ;
00486     }
00487   }
00488 
00489   for (i=0; i<PCG->num_vars; i++) {
00490     PCG->variables[i]=0;
00491   }
00492 
00493   /* Count the # of   reverse crossing  bits   */
00494 /*  for (i=end_of_set1+1; i<PCG->num_proc; i++) {
00495     st_foreach_item(PCG->proc_list[perm[i]].o_list, 
00496                     gen,(char **)&bit_no,(char **)&to_proc) {  
00497       if (PCG->locations[to_proc] ==1)  {
00498         PCG->variables[bit_no]++;
00499       }
00500     }
00501   }
00502   */
00503   for (i=end_of_set1+1; i<PCG->num_proc; i++) 
00504       for (j=0; j<array_n(PCG->proc_list[perm[i]].o_list); j++) {
00505           cur_pair = array_fetch(pair *, PCG->proc_list[perm[i]].o_list, j);
00506           if (PCG->locations[cur_pair->proc_no] ==1)  {
00507               PCG->variables[cur_pair->var_no]++ ;
00508           }      
00509       }
00510 
00511       
00512   for (i=0; i<PCG->num_vars; i++) {
00513     if (PCG->variables[i] > 0) {
00514       ++rev;
00515     }
00516   }
00517 
00518   {
00519     double rev_cost = rev_fac(rev);
00520     result =  ((double) forw) + rev_cost;
00521     number_of_calls++;
00522   }
00523   return result; 
00524 }
00525 
00526 
00539 static void
00540 append_best(
00541   int * opt_perm,
00542   int  loc,
00543   Proc_Com_Graph * PCG)
00544 {
00545   int i,  temp, bestswap, cur_fanout, best_fanout; 
00546   double cur_cost, best_cost;
00547   int j;
00548   pair *cur_pair;
00549     
00550   best_cost = cost_for_cut(PCG, opt_perm, loc);
00551   cur_cost = best_cost;
00552   bestswap = loc;
00553 
00554   best_fanout = 100000;
00555   for(i=loc+1; i<PCG->num_proc;  i++) {
00556       temp = opt_perm[loc];
00557       opt_perm[loc] = opt_perm[i];
00558       opt_perm[i] = temp;
00559       
00560       cur_cost = cost_for_cut(PCG, opt_perm, loc);
00561       
00562       if ( cur_cost == best_cost ) {
00563           cur_fanout = 0;
00564           
00565           for ( j = 0 ; j <= loc ; j++ ) {
00566               PCG->locations[opt_perm[j]] = 1;
00567           }
00568                         
00569           for ( j = loc + 1 ; j < PCG->num_proc ; j++ ) {
00570               PCG->locations[opt_perm[j]] = 2;
00571           }
00572       
00573 /*          st_foreach_item( PCG->proc_list[opt_perm[i]].o_list,
00574                            stgen, ( char ** ) &bit_no, ( char ** )  &to_proc ) {
00575               if ( PCG->locations[to_proc] == 2 ) {
00576                   cur_fanout++;
00577               }
00578           }
00579 */          
00580           for (j=0; j<array_n(PCG->proc_list[opt_perm[i]].o_list); j++) {
00581               cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[i]].o_list, j);
00582               if (PCG->locations[cur_pair->proc_no] ==2)
00583                   cur_fanout++;
00584           }
00585           
00586           
00587           
00588           
00589           if ( cur_fanout < best_fanout ) {
00590               best_fanout = cur_fanout;
00591               bestswap = i;
00592           }
00593       }
00594       
00595       if (cur_cost < best_cost) {
00596           best_cost = cur_cost;
00597           bestswap = i;
00598       }
00599 
00600       temp = opt_perm[loc];
00601       opt_perm[loc] = opt_perm[i];
00602       opt_perm[i] = temp;
00603   }
00604 
00605   temp = opt_perm[loc];
00606   opt_perm[loc] = opt_perm[bestswap];
00607   opt_perm[bestswap] = temp;
00608 }
00609 
00610 
00622 static double
00623 cost_2(
00624   int * opt_perm,
00625   int  loc,
00626   Proc_Com_Graph * PCG)
00627 {
00628     
00629   double cost_0 = cost_for_cut(PCG, opt_perm, loc);
00630   double cost_1 = cost_for_cut(PCG, opt_perm, loc+1);
00631   double result = cost_0 + cost_1;
00632   
00633   return result;
00634     
00635 }
00636 
00637 
00649 static long int
00650 cost_touati_2(
00651   int * opt_perm,
00652   int  loc,
00653   Proc_Com_Graph * PCG)
00654 {
00655   int i, j;
00656   long int result;
00657   pair *cur_pair;
00658 
00659 
00660   for (i=0; i<loc; i++) {
00661       PCG->locations[opt_perm[i]]=1;
00662   }
00663 
00664   for (i=loc+1; i<PCG->num_proc; i++) {
00665       PCG->locations[opt_perm[i]]=0;
00666   }
00667 
00668   for (i=0; i<PCG->num_vars; i++)
00669       PCG->variables[i]=0;
00670   
00671 /*  st_foreach_item(PCG->proc_list[opt_perm[loc]].i_list, 
00672                   gen,(char **)&bit_no,(char **)&from_proc) {  
00673     if (PCG->locations[from_proc] == 0)  {
00674       PCG->variables[bit_no]++ ;
00675     }
00676   }
00677 */
00678   
00679   for (j=0; j<array_n(PCG->proc_list[opt_perm[loc]].i_list); j++) {
00680       cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[loc]].i_list, j);
00681       if (PCG->locations[cur_pair->proc_no] ==0)  {
00682           PCG->variables[cur_pair->var_no]++ ;
00683       }      
00684   }
00685 
00686   result = 0;
00687   for (i=0; i<PCG->num_vars; i++)  {
00688     if (PCG->variables[i] != 0) {
00689       result++;
00690     }
00691   }
00692                                                               
00693   for (i=0; i<PCG->num_vars; i++)
00694       PCG->variables[i]=0;
00695 
00696 /*  st_foreach_item(PCG->proc_list[opt_perm[loc+1]].i_list, 
00697                   gen,(char **)&bit_no,(char **)&from_proc) {  
00698     if (PCG->locations[from_proc] == 0)  {
00699       PCG->variables[bit_no]++ ;
00700     }
00701   }
00702   */
00703 
00704   for (j=0; j<array_n(PCG->proc_list[opt_perm[loc+1]].i_list); j++) {
00705       cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[loc+1]].i_list, j);
00706       if (PCG->locations[cur_pair->proc_no] ==0)  {
00707           PCG->variables[cur_pair->var_no]++ ;
00708       }      
00709   }
00710   
00711   for (i=0; i<PCG->num_vars; i++)  {
00712     if (PCG->variables[i] != 0) {
00713       result++;
00714     }
00715   }
00716 
00717   return result;
00718 }
00719 
00720 
00732 static void
00733 swap(
00734   int * opt_perm,
00735   int  i,
00736   int  j)
00737 {
00738   int temp;
00739 
00740   temp = opt_perm[i];
00741   opt_perm[i] = opt_perm[j];
00742   opt_perm[j] = temp;
00743 }
00744 
00745 
00757 static void
00758 append_best_2(
00759   int * opt_perm,
00760   int  loc,
00761   Proc_Com_Graph * PCG)
00762 {
00763   double best_cost, cur_cost;
00764   int i,j;
00765   int best[2];
00766 
00767 
00768   best_cost = cost_2(opt_perm, loc, PCG); 
00769   cur_cost =  best_cost;
00770   best[0] = loc;
00771   best[1] = loc+1;
00772 
00773   for(i=loc; i<PCG->num_proc;  i++) {
00774     swap(opt_perm,loc,i);
00775     for(j=loc+1; j<PCG->num_proc;  j++) {
00776       swap(opt_perm,loc+1,j);
00777       cur_cost = cost_2(opt_perm, loc, PCG);
00778       if (cur_cost < best_cost) {
00779         best_cost = cur_cost;
00780         best[0] = i;
00781         best[1] = j;
00782       };
00783       swap(opt_perm,loc+1,j);
00784     }
00785     swap(opt_perm,loc,i);
00786   };
00787 
00788   swap(opt_perm,loc,best[0]);
00789   swap(opt_perm,loc+1,best[1]);
00790 }
00791 
00792 
00804 static void
00805 append_touati_2(
00806   int * opt_perm,
00807   int  loc,
00808   Proc_Com_Graph * PCG)
00809 {
00810   long int best_cost, cur_cost;
00811   int i,j;
00812   int best[2];
00813 
00814   /*
00815    * FIX: this is the same function as append_best_2, except that
00816    * cost_touati_2 is used rather than cost_2; just pass the cost function in
00817    * as a parameter.
00818    */
00819 
00820   best_cost = cost_touati_2(opt_perm, loc, PCG); 
00821   cur_cost =  best_cost;
00822   best[0] = loc;
00823   best[1] = loc+1;
00824 
00825   for(i=loc; i<PCG->num_proc;  i++) {
00826     swap(opt_perm,loc,i);
00827     for(j=loc+1; j<PCG->num_proc;  j++) {
00828       swap(opt_perm,loc+1,j);
00829       cur_cost = cost_touati_2(opt_perm, loc, PCG);
00830       if (cur_cost < best_cost) {
00831         best_cost = cur_cost;
00832         best[0] = i;
00833         best[1] = j;
00834       };
00835       swap(opt_perm,loc+1,j);
00836     }
00837     swap(opt_perm,loc,i);
00838   };
00839 
00840   swap(opt_perm,loc,best[0]);
00841   swap(opt_perm,loc+1,best[1]);
00842 }
00843 
00844 
00859 static void
00860 init_heur(
00861   Proc_Com_Graph * PCG,
00862   int * opt_perm)
00863 {
00864   int i;  
00865       
00866   for(i=0; i<PCG->num_proc; i++) {
00867     opt_perm[i]  = i;
00868   }
00869 
00870   
00871   
00872   /*printf("\nEntering ordering code:\n");*/
00873   for(i=0; i<PCG->num_proc; i++)  {
00874     /*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
00875     append_best(opt_perm,  i,  PCG); 
00876   }
00877   /*printf("\n\t--- Total number of calls = %d ---\n",  number_of_calls );*/
00878 }
00879 
00880 
00892 static void
00893 heur_2(
00894   Proc_Com_Graph * PCG,
00895   int * opt_perm)
00896 {
00897 
00898   int i;
00899 
00900   for(i=0; i<PCG->num_proc; i++) {
00901     opt_perm[i]  = i;
00902   }
00903 
00904   for(i=0; i<(2*floor(((double)PCG->num_proc) / 2.0 )); i = i+2) { 
00905     /*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
00906     append_best_2(opt_perm,i,PCG);
00907   }
00908 }
00909 
00910 
00922 static void
00923 heur_touati_la2(
00924   Proc_Com_Graph * PCG,
00925   int * opt_perm)
00926 {
00927   int i;
00928 
00929   for(i=0; i<PCG->num_proc; i++) {
00930     opt_perm[i]  = i;
00931   }
00932 
00933   for(i=0; i<(2*floor(((double)PCG->num_proc) / 2.0 )); i = i+2) {
00934                                 /*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
00935     append_touati_2(opt_perm,i,PCG);
00936   }
00937 }
00938 
00939 
00951 static int *
00952 opt_proc_order(
00953   Proc_Com_Graph * PCG)
00954 {
00955   int *cur_opt;
00956 
00957         
00958   cur_opt = ALLOC(int, PCG->num_proc);
00959   heur_2(PCG, cur_opt);
00960     
00961   /*for (i=0;i<PCG->num_proc; i++) printf(" %d ",cur_opt[i]+1);*/
00962 
00963   return  cur_opt;
00964 }
00965 
00966 
00978 static int *
00979 opt_touati_order(
00980   Proc_Com_Graph * PCG)
00981 {
00982   int *cur_opt;
00983 
00984 
00985   /*
00986    * FIX: same function as opt_proc_order except for heuristic call.
00987    */
00988   
00989   cur_opt = ALLOC(int, PCG->num_proc);
00990   heur_touati_la2(PCG, cur_opt);
00991     
00992   /*for (i=0;i<PCG->num_proc; i++) printf(" %d ",cur_opt[i]+1);*/
00993 
00994   return  cur_opt;
00995 }
00996  
01008 static double
01009 cost_total(
01010   Proc_Com_Graph * PCG,
01011   int * perm)
01012 {
01013   int i;
01014 
01015   double cost=0;
01016 
01017   for(i=0; i<PCG->num_proc-1; i++) {
01018     cost += cost_for_cut(PCG, perm, i);
01019   }
01020         
01021   return  cost;
01022 }
01023 
01024 
01036 static int *
01037 random_permutation(
01038   int  seed,
01039   int  n_elts)
01040 {
01041   int i, j;
01042   int *permutation;
01043   int *remaining;
01044   int next_entry;
01045   int next_value;
01046   int n_entries;
01047 
01048   if (n_elts <= 0) {
01049     return NIL(int);
01050   }
01051 
01052   n_entries = n_elts;
01053   permutation = ALLOC(int, n_entries);
01054   remaining = ALLOC(int, n_entries);
01055   for (i = 0; i < n_entries; i++) {
01056     remaining[i] = i;
01057   }
01058 
01059   util_srandom((long) seed);
01060 
01061   next_entry = 0;
01062   for (; n_entries > 0; n_entries--) {
01063     next_value = util_random() % n_entries;
01064     permutation[next_entry++] = remaining[next_value];
01065     for (j = next_value; j < n_entries - 1; j++) {
01066       remaining[j] = remaining[j + 1];
01067     }
01068   }
01069   FREE(remaining);
01070   return permutation;
01071 }