VIS

src/img/imgMlp.c

Go to the documentation of this file.
00001 
00036 #include "imgInt.h"
00037 #include "fsm.h"
00038 
00039 static char rcsid[] UNUSED = "$Id: imgMlp.c,v 1.31 2005/04/26 19:08:33 jinh Exp $";
00040 
00041 
00042 /*---------------------------------------------------------------------------*/
00043 /* Constant declarations                                                     */
00044 /*---------------------------------------------------------------------------*/
00045 
00046 /*---------------------------------------------------------------------------*/
00047 /* Type declarations                                                         */
00048 /*---------------------------------------------------------------------------*/
00049 
00050 
00051 /*---------------------------------------------------------------------------*/
00052 /* Structure declarations                                                    */
00053 /*---------------------------------------------------------------------------*/
00054 
00063 typedef struct RcInfo_s {
00064   int   pos;    /* level */
00065   int   lNum;
00066   int   lMin;   /* index */
00067   int   lMax;   /* index */
00068   int   gNum;
00069   int   gMin;   /* index */
00070   int   gMax;   /* index */
00071   int   prevG;  /* level */
00072   int   nextG;  /* level */
00073   union {
00074     struct {
00075       bdd_t     *func;
00076       array_t   *nsVarBddArray;
00077     } row;
00078     struct {
00079       bdd_t     *var;
00080       int       type;
00081     } col;
00082   } data;
00083 } RcInfo_t;
00084 
00092 typedef struct RcList_s {
00093   int                   index;
00094   int                   otherIndex;
00095   struct RcList_s       *next;
00096   struct RcList_s       *prev;
00097 } RcList_t;
00098 
00107 typedef struct RcListInfo_s {
00108   int           num;
00109   int           maxNum;
00110   int           curIndex;
00111   st_table      *table;
00112   RcList_t      *cur;
00113   RcList_t      *head;
00114   RcList_t      *tail;
00115 } RcListInfo_t;
00116 
00124 typedef struct ClusterList_s {
00125   int                   flag;   /* 0 : to be conjuncted
00126                                    1 : start element
00127                                    2 : last element
00128                                    3 : isolated
00129                                 */
00130   int                   start;
00131   int                   end;
00132   char                  *supports;
00133   int                   minCol; /* index */
00134   int                   maxCol; /* index */
00135   int                   nSupports;
00136   float                 affinity;
00137   int                   nQuantifyVars;
00138   mdd_t                 *product;
00139   array_t               *nsVarBddArray;
00140   struct ClusterList_s  *prev;
00141   struct ClusterList_s  *next;
00142 } ClusterList_t;
00143 
00151 typedef struct ClusterSortedList_s {
00152   ClusterList_t                 *list;
00153   struct ClusterSortedList_s    *next;
00154 } ClusterSortedList_t;
00155 
00164 typedef struct SccList_s {
00165   int                   startFunc;
00166   int                   lastFunc;
00167   int                   startVar;
00168   int                   lastVar;
00169   int                   nFuncs;
00170   int                   nVars;
00171   struct SccList_s      *next;
00172 } SccList_t;
00173 
00182 typedef struct LatchList_s {
00183   int           number;
00184   int           bddId;
00185   mdd_t         *relation;
00186   st_table      *table;
00187 } LatchList_t;
00188 
00189 
00190 /*---------------------------------------------------------------------------*/
00191 /* Variable declarations                                                     */
00192 /*---------------------------------------------------------------------------*/
00193 
00194 static  int     nMoves;
00195 
00196 
00197 /*---------------------------------------------------------------------------*/
00198 /* Macro declarations                                                        */
00199 /*---------------------------------------------------------------------------*/
00200 
00201 
00204 /*---------------------------------------------------------------------------*/
00205 /* Static function prototypes                                                */
00206 /*---------------------------------------------------------------------------*/
00207 
00208 static void SetupMlp(mdd_manager *mddManager, char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *varPos, array_t *nsVarBddArray, int *nActiveRows, int *nActiveCols, array_t *nonAppearingVarBddArray, Img_DirectionType direction, ImgTrmOption_t *option);
00209 static SccList_t * MlpDecomposeScc(mdd_manager *mddManager, char **xy, int nRows, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int clusteredFlag, ImgTrmOption_t *option);
00210 static int SccSortListIncreasingWithVars(const void *p1, const void *p2);
00211 static int SccSortListDecreasingWithVars(const void *p1, const void *p2);
00212 static int SccSortListIncreasingWithArea(const void *p1, const void *p2);
00213 static int SccSortListDecreasingWithArea(const void *p1, const void *p2);
00214 static int SccSortListIncreasingWithRatio(const void *p1, const void *p2);
00215 static int SccSortListDecreasingWithRatio(const void *p1, const void *p2);
00216 static int SccSortRc(const void *p1, const void *p2);
00217 static void FreeSccList(SccList_t *sccHeadList);
00218 static int NumOfSccs(SccList_t *sccHeadList);
00219 static void BlockLowerTriangle(char **xy, int nRows, int nCols, int nActiveRows, int nActiveCols, SccList_t *sccList, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, ImgTrmOption_t *option);
00220 static void MoveBestRows(char **xy, SccList_t *sccList, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar, ImgTrmOption_t *option);
00221 static void MoveBestCols(char **xy, SccList_t *sccList, int nRows, int nCols, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar, ImgTrmOption_t *option);
00222 static void MlpPostProcess(char **xy, SccList_t *sccList, int nVars, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, Img_DirectionType direction, ImgTrmOption_t *option);
00223 static float ComputeLambdaMlp(char **xy, int nVars, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, Img_DirectionType direction, int mode, int asIs, ImgTrmOption_t *option);
00224 static void FindAndMoveSingletonRows(char **xy, SccList_t *sccList, int nRows, int nCols, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, ImgTrmOption_t *option);
00225 static int MoveSingletonRow(char **xy, SccList_t *sccList, int nRows, int nCols, int x, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, ImgTrmOption_t *option);
00226 static void FindAndMoveSingletonCols(char **xy, SccList_t *sccList, int nRows, int nCols, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, ImgTrmOption_t *option);
00227 static int MoveSingletonCol(char **xy, SccList_t *sccList, int nRows, int nCols, int y, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, ImgTrmOption_t *option);
00228 static void MoveRowToTop(char **xy, int x, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
00229 static void MoveColToLeft(char **xy, int y, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
00230 static void MoveRowToBottom(char **xy, int x, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
00231 static void MoveColToRight(char **xy, int y, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
00232 static void PrintMatrix(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar);
00233 static void PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols, int *rowOrder, int *colOrder, Img_DirectionType direction);
00234 static void PrintClusterMatrix(ClusterList_t *headCluster, int nCols, int *colOrder, Img_DirectionType direction);
00235 static void CheckMatrix(char **xy, SccList_t *sccList, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int startFunc, int lastFunc, int startVar, int lastVar, int local);
00236 static void CheckCluster(ClusterList_t *headCluster, int nCols, RcInfo_t *colInfo, int *colOrder);
00237 static void WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo);
00238 static void PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
00239 static void PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
00240 static RcListInfo_t * SortedListAlloc(void);
00241 static void SortedListFree(RcListInfo_t *candList);
00242 static void SortedListInsert(RcListInfo_t *candList, int index, int otherIndex, RcInfo_t *otherInfo, int method);
00243 static void SortedListDelete(RcListInfo_t *candList, int index);
00244 static void SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method);
00245 static void CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method);
00246 static void MlpCluster(mdd_manager *mddManager, char **xy, int nRows, int nCols, int nActiveRows, int nActiveCols, int *nClusterRows, int *nClusterCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, array_t *clusterArray, array_t *arraySmoothVarBddArray, Img_DirectionType direction, int *cRowOrder, array_t *nsVarBddArray, int *sccBorder, int *varPos, ImgTrmOption_t *option);
00247 static int MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols);
00248 static float MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList, RcInfo_t *colInfo, int *colOrder, int nActiveCols, int clusterMethod);
00249 static int RecursiveCluster(mdd_manager *mddManager, ClusterList_t *headCluster, ClusterSortedList_t *clusterSortedList, char **xy, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int nActiveRows, int nClusterCols, Img_DirectionType direction, int *varPos, int moveFlag, ImgTrmOption_t *option);
00250 static int RemoveLocalVarsInCluster(mdd_manager *mddManager, char **xy, ClusterList_t *list, int nActiveRows, int nClusterCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int moveFlag, ImgTrmOption_t *option);
00251 static int MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *colOrder, int nClusterCols);
00252 static ClusterSortedList_t * ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList, ClusterList_t *list, int useQuantifyVars);
00253 static int CountClusterList(ClusterList_t *clusterList);
00254 static int CountClusterSortedList(ClusterSortedList_t *clusterSortedList);
00255 static array_t * CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray, ImgFunctionData_t *functionData, array_t *nsVarBddArray, ImgTrmOption_t *option);
00256 static void SortCol(char **xy, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder);
00257 static void UpdateDisapearingPsVars(mdd_manager *mddManager, char **xy, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int row, ImgTrmOption_t *option);
00258 static void UpdateDisapearingPsVarsInCluster(mdd_manager *mddManager, char **xy, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, ClusterList_t *list, int moveFlag, ImgTrmOption_t *option);
00259 static void UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray, int nRows, RcInfo_t *rowInfo, int *rowOrder, array_t *nonAppearingVarBddArray);
00260 static void WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo);
00261 
00265 /*---------------------------------------------------------------------------*/
00266 /* Definition of exported functions                                          */
00267 /*---------------------------------------------------------------------------*/
00268 
00269 
00281 void
00282 Img_PrintMlpOptions(void)
00283 {
00284   ImgTrmOption_t        *options;
00285   char                  dummy[80];
00286 
00287   options = ImgGetTrmOptions();
00288 
00289   switch (options->mlpCluster) {
00290   case 0 :
00291     sprintf(dummy, "linear clustering");
00292     break;
00293   case 1 :
00294     sprintf(dummy, "affinity based tree clustering (default)");
00295     break;
00296   default :
00297     sprintf(dummy, "invalid");
00298     break;
00299   }
00300   fprintf(vis_stdout, "MLP: mlp_cluster = %d (%s)\n",
00301           options->mlpCluster, dummy);
00302 
00303   switch (options->mlpReorder) {
00304   case 0 :
00305     sprintf(dummy, "no reordering after clustering (default)");
00306     break;
00307   case 1 :
00308     sprintf(dummy, "reorder using MLP after clustering (inside)");
00309     break;
00310   case 2 :
00311     sprintf(dummy, "reorder using MLP after clustering (outside)");
00312     break;
00313   case 3 :
00314     sprintf(dummy, "reorder using IWLS95 after clustering");
00315     break;
00316   default :
00317     sprintf(dummy, "invalid");
00318     break;
00319   }
00320   fprintf(vis_stdout, "MLP: mlp_reorder = %d (%s)\n",
00321           options->mlpReorder, dummy);
00322 
00323   switch (options->mlpPreReorder) {
00324   case 0 :
00325     sprintf(dummy, "no reordering after clustering (default)");
00326     break;
00327   case 1 :
00328     sprintf(dummy, "reorder using MLP after clustering (inside)");
00329     break;
00330   case 2 :
00331     sprintf(dummy, "reorder using MLP after clustering (outside)");
00332     break;
00333   case 3 :
00334     sprintf(dummy, "reorder using IWLS95 after clustering");
00335     break;
00336   default :
00337     sprintf(dummy, "invalid");
00338     break;
00339   }
00340   fprintf(vis_stdout, "MLP: mlp_pre_reorder = %d (%s)\n",
00341           options->mlpPreReorder, dummy);
00342 
00343   switch (options->mlpPostProcess) {
00344   case 0 :
00345     sprintf(dummy, "no postprocessing (default)");
00346     break;
00347   case 1 :
00348     sprintf(dummy, "do postprocessing after ordering");
00349     break;
00350   case 2 :
00351     sprintf(dummy, "do postprocessing after clustering or reordering");
00352     break;
00353   case 3 :
00354     sprintf(dummy, "do both 1 and 2");
00355     break;
00356   default :
00357     sprintf(dummy, "invalid");
00358     break;
00359   }
00360   fprintf(vis_stdout, "MLP: mlp_postprocess = %d (%s)\n",
00361           options->mlpPostProcess, dummy);
00362 }
00363 
00364 
00365 /*---------------------------------------------------------------------------*/
00366 /* Definition of internal functions                                          */
00367 /*---------------------------------------------------------------------------*/
00368 
00369 
00379 bdd_t *
00380 ImgMlpMultiwayAndSmooth(mdd_manager *mddManager,
00381                         ImgFunctionData_t *functionData,
00382                         array_t *relationArray,
00383                         array_t *domainVarBddArray,
00384                         array_t *quantifyVarBddArray,
00385                         array_t *rangeVarBddArray,
00386                         Img_DirectionType direction,
00387                         ImgTrmOption_t *option)
00388 {
00389   int           i, clusterSize;
00390   array_t       *clusteredRelationArray;
00391   mdd_t         *result, *relation, *tmp;
00392 
00393   if (direction == Img_Forward_c) {
00394     if (array_n(domainVarBddArray) == 0 && array_n(quantifyVarBddArray) == 0) {
00395       if (array_n(relationArray) == 1) {
00396         relation = array_fetch(mdd_t *, relationArray, 0);
00397         result = bdd_dup(relation);
00398       } else {
00399         result = array_fetch(mdd_t *, relationArray, 0);
00400         for (i = 1; i < array_n(relationArray); i++) {
00401           relation = array_fetch(mdd_t *, relationArray, i);
00402           tmp = result;
00403           result = bdd_and(tmp, relation, 1, 1);
00404           mdd_free(tmp);
00405         }
00406       }
00407       return(result);
00408     }
00409   }
00410 
00411   clusterSize = option->clusterSize;
00412   option->clusterSize = 1000000000;
00413   ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
00414                 domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
00415                 direction, &clusteredRelationArray, NIL(array_t *), option);
00416   option->clusterSize = clusterSize;
00417 
00418   assert(array_n(clusteredRelationArray) == 1);
00419   result = array_fetch(mdd_t *, clusteredRelationArray, 0);
00420   array_free(clusteredRelationArray);
00421 
00422   return(result);
00423 }
00424 
00425 
00438 void
00439 ImgMlpClusterRelationArray(mdd_manager *mddManager,
00440                         ImgFunctionData_t *functionData,
00441                         array_t *relationArray,
00442                         array_t *domainVarBddArray,
00443                         array_t *quantifyVarBddArray,
00444                         array_t *rangeVarBddArray,
00445                         Img_DirectionType direction,
00446                         array_t **clusteredRelationArrayPtr,
00447                         array_t **arraySmoothVarBddArrayPtr,
00448                         ImgTrmOption_t *option)
00449 {
00450   int           i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
00451   int           *rowOrder, *colOrder, *cRowOrder;
00452   RcInfo_t      *rowInfo, *colInfo;
00453   char          **xy;
00454   int           nClusterRows, nClusterCols;
00455   array_t       *clusterArray;
00456   bdd_t         *cluster, *relation, *tempCluster, *var, *nsVar;
00457   int           row, col, s, t;
00458   array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
00459   int           qVarPos;
00460   array_t       *nonAppearingVarBddArray;
00461   int           *varPos;
00462   array_t       *psVarBddArray, *nsVarBddArray;
00463   int           index, nVars, nc;
00464   long          initialTime, finalTime;
00465   array_t       *clusteredRelationArray;
00466   SccList_t     *sccHeadList, *sccList;
00467   int           *sccBorder;
00468   float         lambda1, lambda2, lambda3;
00469   FILE          *fout;
00470 
00471   if (option->mlpVerbosity)
00472     initialTime = util_cpu_time();
00473   else
00474     initialTime = 0;
00475 
00476   psVarBddArray = domainVarBddArray;
00477   nsVarBddArray = rangeVarBddArray;
00478 
00479   if (option->mlpInitialCluster && functionData) {
00480     clusteredRelationArray = CreateInitialCluster(mddManager, relationArray,
00481                                                   functionData, nsVarBddArray,
00482                                                   option);
00483   } else
00484     clusteredRelationArray = relationArray;
00485 
00486   nRows = array_n(clusteredRelationArray);
00487   if (direction == Img_Forward_c)
00488     nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
00489   else
00490     nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
00491 
00492   xy = ALLOC(char *, nRows);
00493   for (i = 0; i < nRows; i++) {
00494     xy[i] = ALLOC(char, nCols);
00495     memset(xy[i], 0, sizeof(char) * nCols);
00496   }
00497 
00498   rowOrder = ALLOC(int, nRows);
00499   for (i = 0; i < nRows; i++)
00500     rowOrder[i] = i;
00501   colOrder = ALLOC(int, nCols);
00502   for (i = 0; i < nCols; i++)
00503     colOrder[i] = i;
00504 
00505   rowInfo = ALLOC(RcInfo_t, nRows);
00506   memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
00507   colInfo = ALLOC(RcInfo_t, nCols);
00508   memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
00509   nVars = bdd_num_vars(mddManager);
00510   varPos = ALLOC(int, nVars);
00511   memset(varPos, 0, sizeof(int) * nVars);
00512 
00513   for (i = 0; i < nRows; i++) {
00514     relation = array_fetch(bdd_t *, clusteredRelationArray, i);
00515     rowInfo[i].data.row.func = bdd_dup(relation);
00516   }
00517 
00518   nc = 0;
00519   for (i = 0; i < array_n(psVarBddArray); i++) {
00520     var = array_fetch(bdd_t *, psVarBddArray, i);
00521     colInfo[nc].data.col.var = var;
00522     colInfo[nc].data.col.type = 1;
00523     index = (int)bdd_top_var_id(var);
00524     varPos[index] = nc;
00525     nc++;
00526   }
00527   for (i = 0; i < array_n(quantifyVarBddArray); i++) {
00528     var = array_fetch(bdd_t *, quantifyVarBddArray, i);
00529     colInfo[nc].data.col.var = var;
00530     colInfo[nc].data.col.type = 2;
00531     index = (int)bdd_top_var_id(var);
00532     varPos[index] = nc;
00533     nc++;
00534   }
00535 
00536   if (arraySmoothVarBddArrayPtr)
00537     nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
00538   else
00539     nonAppearingVarBddArray = NIL(array_t);
00540 
00541   SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
00542            rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
00543            nonAppearingVarBddArray, direction, option);
00544 
00545   if (nActiveRows == 0) {
00546     clusterArray = array_alloc(mdd_t *, 0);
00547     cluster = bdd_one(mddManager);
00548     for (i = nActiveRows; i < nRows; i++) {
00549       row = rowOrder[i];
00550       relation = rowInfo[row].data.row.func;
00551       tempCluster = bdd_and(cluster, relation, 1, 1);
00552       bdd_free(cluster);
00553       cluster = tempCluster;
00554     }
00555     array_insert_last(bdd_t *, clusterArray, cluster);
00556     *clusteredRelationArrayPtr = clusterArray;
00557 
00558     if (arraySmoothVarBddArrayPtr) {
00559       arraySmoothVarBddArray = array_alloc(array_t *, 0);
00560       *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
00561       array_insert_last(array_t *, arraySmoothVarBddArray,
00562                         nonAppearingVarBddArray);
00563       if (direction == Img_Forward_c) {
00564         smoothVarBddArray = array_alloc(array_t *, 0);
00565         array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
00566       } else {
00567         smoothVarBddArray = array_alloc(array_t *, 0);
00568         for (i = 0; i < nRows; i++) {
00569           row = rowOrder[i];
00570           for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
00571             nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
00572                                 j);
00573             array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
00574           }
00575         }
00576         array_insert_last(array_t *, arraySmoothVarBddArray,
00577                           smoothVarBddArray);
00578       }
00579     }
00580 
00581     FREE(varPos);
00582     for (i = 0; i < nRows; i++) {
00583       if (xy[i])
00584         FREE(xy[i]);
00585     }
00586     FREE(xy);
00587     FREE(rowOrder);
00588     FREE(colOrder);
00589     for (i = 0; i < nRows; i++) {
00590       bdd_free(rowInfo[i].data.row.func);
00591       if (rowInfo[i].data.row.nsVarBddArray)
00592         array_free(rowInfo[i].data.row.nsVarBddArray);
00593     }
00594     FREE(rowInfo);
00595     FREE(colInfo);
00596     return;
00597   }
00598   sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
00599                                 rowOrder, colOrder, rowInfo, colInfo,
00600                                 0, option);
00601   if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00602     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
00603                 rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
00604   }
00605   sccList = sccHeadList;
00606   while (sccList) {
00607     BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
00608                         rowOrder, colOrder, rowInfo, colInfo, option);
00609     sccList = sccList->next;
00610   }
00611   if (option->mlpVerbosity >= 2) {
00612     lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
00613                                 rowInfo, colInfo, rowOrder, colOrder,
00614                                 direction, 0, 0, option);
00615     lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
00616                                 rowInfo, colInfo, rowOrder, colOrder,
00617                                 direction, 1, 0, option);
00618     lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
00619                                 rowInfo, colInfo, rowOrder, colOrder,
00620                                 direction, 2, 0, option);
00621     fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
00622             lambda1, lambda2, lambda3);
00623   }
00624 
00625   if (option->mlpVerbosity) {
00626     finalTime = util_cpu_time();
00627     fprintf(vis_stdout, "time for MLP = %10g\n",
00628            (double)(finalTime - initialTime) / 1000.0);
00629   }
00630   if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00631     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
00632                 rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
00633   }
00634 
00635   if (option->mlpPostProcess == 1 || option->mlpPostProcess == 3) {
00636     for (x = 0; x < nActiveRows; x++) {
00637       row = rowOrder[x];
00638       rowInfo[row].lNum = rowInfo[row].gNum;
00639       rowInfo[row].lMin = rowInfo[row].gMin;
00640       rowInfo[row].lMax = rowInfo[row].gMax;
00641       rowInfo[row].prevG = -1;
00642       rowInfo[row].nextG = nActiveCols;
00643     }
00644     for (y = 0; y < nActiveCols; y++) {
00645       col = colOrder[y];
00646       colInfo[col].lNum = colInfo[col].gNum;
00647       colInfo[col].lMin = colInfo[col].gMin;
00648       colInfo[col].lMax = colInfo[col].gMax;
00649       colInfo[col].prevG = -1;
00650       colInfo[col].nextG = nActiveRows;
00651     }
00652 
00653     sccList = sccHeadList;
00654     while (sccList) {
00655       MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
00656                    rowInfo, colInfo, rowOrder, colOrder, direction, option);
00657       sccList = sccList->next;
00658     }
00659     if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00660       PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
00661                   rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
00662     }
00663   }
00664 
00665   if (option->mlpWriteOrder) {
00666     fout = fopen(option->mlpWriteOrder, "w");
00667     if (fout) {
00668       WriteOrder(fout, nActiveCols, colOrder, colInfo);
00669       fclose(fout);
00670     } else {
00671       fprintf(vis_stderr, "** img error: can't open file [%s]\n",
00672               option->mlpWriteOrder);
00673     }
00674   }
00675 
00676   clusterArray = array_alloc(bdd_t *, 0);
00677   if (arraySmoothVarBddArrayPtr) {
00678     arraySmoothVarBddArray = array_alloc(array_t *, 0);
00679     array_insert_last(array_t *, arraySmoothVarBddArray,
00680                         nonAppearingVarBddArray);
00681   } else
00682     arraySmoothVarBddArray = NIL(array_t);
00683 
00684   if ((direction == Img_Forward_c && option->mlpReorder) ||
00685       (direction == Img_Backward_c && option->mlpPreReorder) ||
00686       option->mlpPostProcess >= 2) {
00687     cRowOrder = ALLOC(int, nActiveRows);
00688     for (i = 0; i < nActiveCols; i++) {
00689       col = colOrder[i];
00690       colInfo[col].lNum = 0;
00691       colInfo[col].lMin = nActiveRows;
00692       colInfo[col].lMax = -1;
00693     }
00694   } else
00695     cRowOrder = NIL(int);
00696 
00697   if (option->mlpClusterScc) {
00698     sccBorder = ALLOC(int, nRows);
00699     memset(sccBorder, 0, sizeof(int) * nRows);
00700     sccList = sccHeadList;
00701     while (sccList) {
00702       sccBorder[sccList->startFunc] = 1;
00703       sccBorder[sccList->lastFunc] = 2;
00704       sccList = sccList->next;
00705     }
00706   } else
00707     sccBorder = NIL(int);
00708 
00709   MlpCluster(mddManager, xy, nRows, nCols, nActiveRows, nActiveCols,
00710                 &nClusterRows, &nClusterCols,
00711                 rowOrder, colOrder, rowInfo, colInfo,
00712                 clusterArray, arraySmoothVarBddArray,
00713                 direction, cRowOrder, nsVarBddArray, sccBorder, varPos, option);
00714 
00715   if (sccBorder)
00716     FREE(sccBorder);
00717 
00718   if ((direction == Img_Forward_c && option->mlpReorder) ||
00719       (direction == Img_Backward_c && option->mlpPreReorder) ||
00720       option->mlpPostProcess >= 2) {
00721     if (option->mlpDecomposeScc && NumOfSccs(sccHeadList) > 1) {
00722       FreeSccList(sccHeadList);
00723       sccHeadList = MlpDecomposeScc(mddManager, xy, nRows,
00724                                 nClusterRows, nClusterCols,
00725                                 cRowOrder, colOrder, rowInfo, colInfo,
00726                                 1, option);
00727     } else {
00728       sccHeadList->startFunc = 0;
00729       sccHeadList->lastFunc = nClusterRows - 1;
00730       sccHeadList->startVar = 0;
00731       sccHeadList->lastVar = nClusterCols - 1;
00732       sccHeadList->nFuncs = nClusterRows;
00733       sccHeadList->nVars = nClusterCols;
00734     }
00735     if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00736       PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
00737                   rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
00738     }
00739 
00740     if ((direction == Img_Forward_c && option->mlpReorder) ||
00741         (direction == Img_Backward_c && option->mlpPreReorder)) {
00742       sccList = sccHeadList;
00743       while (sccList) {
00744         BlockLowerTriangle(xy, nRows, nCols, nClusterRows, nClusterCols,
00745                            sccList, cRowOrder, colOrder, rowInfo, colInfo,
00746                            option);
00747         sccList = sccList->next;
00748       }
00749       if (option->mlpVerbosity >= 2) {
00750         lambda1 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
00751                                    rowInfo, colInfo, rowOrder, colOrder,
00752                                    direction, 0, 0, option);
00753         lambda2 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
00754                                    rowInfo, colInfo, rowOrder, colOrder,
00755                                    direction, 1, 0, option);
00756         lambda3 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
00757                                    rowInfo, colInfo, rowOrder, colOrder,
00758                                    direction, 2, 0, option);
00759         fprintf(vis_stdout, "Lambda after MLP-cluster = %f (%f, %f)\n",
00760                 lambda1, lambda2, lambda3);
00761       }
00762 
00763       if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00764         PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
00765                     rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
00766       }
00767     }
00768 
00769     if (option->mlpPostProcess >= 2) {
00770       for (x = 0; x < nClusterRows; x++) {
00771         row = rowOrder[x];
00772         rowInfo[row].lNum = rowInfo[row].gNum;
00773         rowInfo[row].lMin = rowInfo[row].gMin;
00774         rowInfo[row].lMax = rowInfo[row].gMax;
00775         rowInfo[row].prevG = -1;
00776         rowInfo[row].nextG = nClusterCols;
00777       }
00778       for (y = 0; y < nClusterCols; y++) {
00779         col = colOrder[y];
00780         colInfo[col].lNum = colInfo[col].gNum;
00781         colInfo[col].lMin = colInfo[col].gMin;
00782         colInfo[col].lMax = colInfo[col].gMax;
00783         colInfo[col].prevG = -1;
00784         colInfo[col].nextG = nClusterRows;
00785       }
00786 
00787       sccList = sccHeadList;
00788       while (sccList) {
00789         MlpPostProcess(xy, sccList, nCols, nClusterRows, nClusterCols,
00790                      rowInfo, colInfo, cRowOrder, colOrder, direction, option);
00791         sccList = sccList->next;
00792       }
00793       if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
00794         PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
00795                     rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
00796       }
00797     }
00798 
00799     *clusteredRelationArrayPtr = clusterArray;
00800 
00801     if (direction == Img_Forward_c) {
00802       for (i = nClusterRows - 1; i >= 0; i--) {
00803         row = cRowOrder[i];
00804         array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
00805         rowInfo[row].data.row.func = NIL(bdd_t);
00806       }
00807 
00808       if (nRows > nActiveRows) {
00809         cluster = bdd_one(mddManager);
00810         for (i = nActiveRows; i < nRows; i++) {
00811           row = rowOrder[i];
00812           relation = rowInfo[row].data.row.func;
00813           tempCluster = bdd_and(cluster, relation, 1, 1);
00814           bdd_free(cluster);
00815           cluster = tempCluster;
00816         }
00817         array_insert_last(bdd_t *, clusterArray, cluster);
00818       }
00819     } else {
00820       if (nRows > nActiveRows) {
00821         UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
00822                                  rowInfo, cRowOrder, nonAppearingVarBddArray);
00823 
00824         cluster = bdd_one(mddManager);
00825         for (i = nActiveRows; i < nRows; i++) {
00826           row = rowOrder[i];
00827           relation = rowInfo[row].data.row.func;
00828           tempCluster = bdd_and(cluster, relation, 1, 1);
00829           bdd_free(cluster);
00830           cluster = tempCluster;
00831         }
00832         array_insert_last(bdd_t *, clusterArray, cluster);
00833       }
00834 
00835       for (i = 0; i < nClusterRows; i++) {
00836         row = cRowOrder[i];
00837         array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
00838         rowInfo[row].data.row.func = NIL(bdd_t);
00839       }
00840     }
00841 
00842     if (arraySmoothVarBddArrayPtr) {
00843       *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
00844 
00845       if (direction == Img_Forward_c) {
00846         if (nCols > nClusterCols) {
00847           for (i = nClusterCols; i < nCols; i++) {
00848             col = colOrder[i];
00849             array_insert_last(bdd_t *, nonAppearingVarBddArray,
00850                                 bdd_dup(colInfo[col].data.col.var));
00851           }
00852         }
00853         qVarPos = nClusterCols - 1;
00854         if (qVarPos >= 0) {
00855           col = colOrder[qVarPos];
00856           while (colInfo[col].gNum == 0) {
00857             array_insert_last(bdd_t *, nonAppearingVarBddArray,
00858                                 bdd_dup(colInfo[col].data.col.var));
00859             if (qVarPos == 0)
00860               break;
00861             qVarPos--;
00862             col = colOrder[qVarPos];
00863           }
00864         }
00865         for (i = nClusterRows - 1; i >= 0; i--) {
00866           row = cRowOrder[i];
00867           smoothVarBddArray = array_alloc(array_t *, 0);
00868           col = colOrder[qVarPos];
00869           while (rowInfo[colInfo[col].gMin].pos == i) {
00870             array_insert_last(bdd_t *, smoothVarBddArray,
00871                                 bdd_dup(colInfo[col].data.col.var));
00872             if (qVarPos == 0)
00873               break;
00874             qVarPos--;
00875             col = colOrder[qVarPos];
00876           }
00877           array_insert_last(array_t *, arraySmoothVarBddArray,
00878                             smoothVarBddArray);
00879         }
00880 
00881         if (nRows > nActiveRows) {
00882           smoothVarBddArray = array_alloc(array_t *, 0);
00883           array_insert_last(array_t *, arraySmoothVarBddArray,
00884                             smoothVarBddArray);
00885         }
00886       } else {
00887         if (nRows == nActiveRows) {
00888           UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
00889                                    rowInfo, cRowOrder, nonAppearingVarBddArray);
00890         } else {
00891           smoothVarBddArray = array_alloc(array_t *, 0);
00892           for (i = nActiveRows; i < nRows; i++) {
00893             row = rowOrder[i];
00894             for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
00895               nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
00896                                   j);
00897               array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
00898             }
00899           }
00900           array_insert_last(array_t *, arraySmoothVarBddArray,
00901                             smoothVarBddArray);
00902         }
00903         for (i = 0; i < nClusterRows; i++) {
00904           row = cRowOrder[i];
00905           smoothVarBddArray = array_alloc(array_t *, 0);
00906           for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
00907             nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
00908                                 j);
00909             array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
00910           }
00911 
00912           s = colInfo[rowInfo[row].gMin].pos;
00913           t = colInfo[rowInfo[row].gMax].pos;
00914           for (j = s; j <= t; j++) {
00915             col = colOrder[j];
00916             if (colInfo[col].data.col.type == 2) {
00917               if (rowInfo[colInfo[col].gMax].pos == i) {
00918                 array_insert_last(bdd_t *, smoothVarBddArray,
00919                                   bdd_dup(colInfo[col].data.col.var));
00920               }
00921             }
00922           }
00923           array_insert_last(array_t *, arraySmoothVarBddArray,
00924                             smoothVarBddArray);
00925         }
00926       }
00927     }
00928 
00929     FREE(cRowOrder);
00930 
00931     if (option->mlpVerbosity) {
00932       finalTime = util_cpu_time();
00933       fprintf(vis_stdout, "time for MLP-clustering-reorder = %10g\n",
00934               (double)(finalTime - initialTime) / 1000.0);
00935     }
00936   } else {
00937     *clusteredRelationArrayPtr = clusterArray;
00938     if (arraySmoothVarBddArrayPtr)
00939       *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
00940 
00941     if (option->mlpVerbosity) {
00942       finalTime = util_cpu_time();
00943       fprintf(vis_stdout, "time for MLP-clustering = %10g\n",
00944               (double)(finalTime - initialTime) / 1000.0);
00945     }
00946   }
00947 
00948   FreeSccList(sccHeadList);
00949 
00950   FREE(varPos);
00951   for (i = 0; i < nRows; i++) {
00952     if (xy[i])
00953       FREE(xy[i]);
00954   }
00955   FREE(xy);
00956   FREE(rowOrder);
00957   FREE(colOrder);
00958   for (i = 0; i < nRows; i++) {
00959     if (rowInfo[i].data.row.func)
00960       bdd_free(rowInfo[i].data.row.func);
00961     if (rowInfo[i].data.row.nsVarBddArray)
00962       array_free(rowInfo[i].data.row.nsVarBddArray);
00963   }
00964   FREE(rowInfo);
00965   FREE(colInfo);
00966   if (option->mlpInitialCluster)
00967     mdd_array_free(clusteredRelationArray);
00968 }
00969 
00970 
00980 void
00981 ImgMlpOrderRelationArray(mdd_manager *mddManager,
00982                         array_t *relationArray,
00983                         array_t *domainVarBddArray,
00984                         array_t *quantifyVarBddArray,
00985                         array_t *rangeVarBddArray,
00986                         Img_DirectionType direction,
00987                         array_t **orderedRelationArrayPtr,
00988                         array_t **arraySmoothVarBddArrayPtr,
00989                         ImgTrmOption_t *option)
00990 {
00991   int           i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
00992   int           *rowOrder, *colOrder;
00993   RcInfo_t      *rowInfo, *colInfo;
00994   char          **xy;
00995   array_t       *orderedArray;
00996   bdd_t         *relation, *var, *nsVar;
00997   int           row, col, s, t;
00998   array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
00999   int           qVarPos;
01000   array_t       *nonAppearingVarBddArray;
01001   int           *varPos;
01002   array_t       *psVarBddArray, *nsVarBddArray;
01003   int           index, nVars, nc;
01004   long          initialTime, finalTime;
01005   SccList_t     *sccHeadList, *sccList;
01006   float         lambda1, lambda2, lambda3;
01007 
01008   arraySmoothVarBddArray = NIL(array_t);
01009   nRows = array_n(relationArray);
01010   if (direction == Img_Forward_c)
01011     nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
01012   else
01013     nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
01014 
01015   if (nCols == 0) {
01016     if (direction == Img_Forward_c) {
01017       orderedArray = mdd_array_duplicate(relationArray);
01018       *orderedRelationArrayPtr = orderedArray;
01019       if (arraySmoothVarBddArrayPtr) {
01020         arraySmoothVarBddArray = array_alloc(array_t *, 0);
01021         *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
01022         for (i = 0; i <= nRows; i++) {
01023           smoothVarBddArray = array_alloc(array_t *, 0);
01024           array_insert_last(array_t *, arraySmoothVarBddArray,
01025                             smoothVarBddArray);
01026         }
01027       }
01028     } else {
01029       orderedArray = array_alloc(mdd_t *, 0);
01030       array_insert_last(mdd_t *, orderedArray, mdd_one(mddManager));
01031       *orderedRelationArrayPtr = orderedArray;
01032       if (arraySmoothVarBddArrayPtr) {
01033         arraySmoothVarBddArray = array_alloc(array_t *, 0);
01034         *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
01035         for (i = 0; i <= 1; i++) {
01036           smoothVarBddArray = array_alloc(array_t *, 0);
01037           array_insert_last(array_t *, arraySmoothVarBddArray,
01038                             smoothVarBddArray);
01039         }
01040       }
01041     }
01042     return;
01043   }
01044 
01045   if (option->mlpVerbosity)
01046     initialTime = util_cpu_time();
01047   else
01048     initialTime = 0;
01049 
01050   xy = ALLOC(char *, nRows);
01051   for (i = 0; i < nRows; i++) {
01052     xy[i] = ALLOC(char, nCols);
01053     memset(xy[i], 0, sizeof(char) * nCols);
01054   }
01055 
01056   rowOrder = ALLOC(int, nRows);
01057   for (i = 0; i < nRows; i++)
01058     rowOrder[i] = i;
01059   colOrder = ALLOC(int, nCols);
01060   for (i = 0; i < nCols; i++)
01061     colOrder[i] = i;
01062 
01063   rowInfo = ALLOC(RcInfo_t, nRows);
01064   memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
01065   colInfo = ALLOC(RcInfo_t, nCols);
01066   memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
01067   nVars = bdd_num_vars(mddManager);
01068   varPos = ALLOC(int, nVars);
01069   memset(varPos, 0, sizeof(int) * nVars);
01070 
01071   for (i = 0; i < nRows; i++) {
01072     relation = array_fetch(bdd_t *, relationArray, i);
01073     rowInfo[i].data.row.func = bdd_dup(relation);
01074   }
01075 
01076   psVarBddArray = domainVarBddArray;
01077   nsVarBddArray = rangeVarBddArray;
01078   nc = 0;
01079   for (i = 0; i < array_n(psVarBddArray); i++) {
01080     var = array_fetch(bdd_t *, psVarBddArray, i);
01081     colInfo[nc].data.col.var = var;
01082     colInfo[nc].data.col.type = 1;
01083     index = (int)bdd_top_var_id(var);
01084     varPos[index] = nc;
01085     nc++;
01086   }
01087   for (i = 0; i < array_n(quantifyVarBddArray); i++) {
01088     var = array_fetch(bdd_t *, quantifyVarBddArray, i);
01089     colInfo[nc].data.col.var = var;
01090     colInfo[nc].data.col.type = 2;
01091     index = (int)bdd_top_var_id(var);
01092     varPos[index] = nc;
01093     nc++;
01094   }
01095 
01096   if (arraySmoothVarBddArrayPtr)
01097     nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
01098   else
01099     nonAppearingVarBddArray = NIL(array_t);
01100   SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
01101            rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
01102            nonAppearingVarBddArray, direction, option);
01103   if (nActiveRows == 0) {
01104     orderedArray = array_alloc(bdd_t *, 0);
01105     if (arraySmoothVarBddArrayPtr) {
01106       arraySmoothVarBddArray = array_alloc(array_t *, 0);
01107       array_insert_last(array_t *, arraySmoothVarBddArray,
01108                         nonAppearingVarBddArray);
01109     }
01110     for (i = 0; i < nRows; i++) {
01111       row = rowOrder[i];
01112       relation = rowInfo[row].data.row.func;
01113       array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
01114       if (arraySmoothVarBddArrayPtr) {
01115         if (direction == Img_Forward_c) {
01116           smoothVarBddArray = array_alloc(array_t *, 0);
01117           array_insert_last(array_t *, arraySmoothVarBddArray,
01118                             smoothVarBddArray);
01119         } else {
01120           smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
01121           rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
01122           array_insert_last(array_t *, arraySmoothVarBddArray,
01123                             smoothVarBddArray);
01124         }
01125       }
01126     }
01127     *orderedRelationArrayPtr = orderedArray;
01128     if (arraySmoothVarBddArrayPtr)
01129       *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
01130 
01131     FREE(varPos);
01132     for (i = 0; i < nRows; i++) {
01133       if (xy[i])
01134         FREE(xy[i]);
01135     }
01136     FREE(xy);
01137     FREE(rowOrder);
01138     FREE(colOrder);
01139     for (i = 0; i < nRows; i++) {
01140       bdd_free(rowInfo[i].data.row.func);
01141       if (rowInfo[i].data.row.nsVarBddArray)
01142         array_free(rowInfo[i].data.row.nsVarBddArray);
01143     }
01144     FREE(rowInfo);
01145     FREE(colInfo);
01146     return;
01147   }
01148   sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
01149                                 rowOrder, colOrder, rowInfo, colInfo,
01150                                 0, option);
01151   if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
01152     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
01153                 rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
01154   }
01155   sccList = sccHeadList;
01156   while (sccList) {
01157     BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
01158                         rowOrder, colOrder, rowInfo, colInfo, option);
01159     sccList = sccList->next;
01160   }
01161   if (option->mlpVerbosity >= 2) {
01162     lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01163                                 rowInfo, colInfo, rowOrder, colOrder,
01164                                 direction, 0, 0, option);
01165     lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01166                                 rowInfo, colInfo, rowOrder, colOrder,
01167                                 direction, 1, 0, option);
01168     lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01169                                 rowInfo, colInfo, rowOrder, colOrder,
01170                                 direction, 2, 0, option);
01171     fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
01172             lambda1, lambda2, lambda3);
01173   }
01174 
01175   if (option->mlpVerbosity) {
01176     finalTime = util_cpu_time();
01177     fprintf(vis_stdout, "time for MLP = %10g\n",
01178            (double)(finalTime - initialTime) / 1000.0);
01179   }
01180   if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
01181     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
01182                 rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
01183   }
01184 
01185   if (option->mlpPostProcess) {
01186     for (x = 0; x < nRows; x++) {
01187       row = rowOrder[x];
01188       rowInfo[row].lNum = rowInfo[row].gNum;
01189       rowInfo[row].lMin = rowInfo[row].gMin;
01190       rowInfo[row].lMax = rowInfo[row].gMax;
01191       rowInfo[row].prevG = -1;
01192       rowInfo[row].nextG = nCols;
01193     }
01194     for (y = 0; y < nCols; y++) {
01195       col = colOrder[y];
01196       colInfo[col].lNum = colInfo[col].gNum;
01197       colInfo[col].lMin = colInfo[col].gMin;
01198       colInfo[col].lMax = colInfo[col].gMax;
01199       colInfo[col].prevG = -1;
01200       colInfo[col].nextG = nRows;
01201     }
01202 
01203     sccList = sccHeadList;
01204     while (sccList) {
01205       MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
01206                    rowInfo, colInfo, rowOrder, colOrder, direction, option);
01207       sccList = sccList->next;
01208     }
01209     if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
01210       PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
01211                   rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
01212     }
01213   }
01214 
01215   orderedArray = array_alloc(bdd_t *, 0);
01216   if (arraySmoothVarBddArrayPtr) {
01217     arraySmoothVarBddArray = array_alloc(array_t *, 0);
01218     array_insert_last(array_t *, arraySmoothVarBddArray,
01219                         nonAppearingVarBddArray);
01220   }
01221 
01222   assert(nActiveCols > 0);
01223   if (direction == Img_Forward_c) {
01224     if (arraySmoothVarBddArrayPtr) {
01225       if (nCols > nActiveCols) {
01226         for (i = nActiveCols; i < nCols; i++) {
01227           col = colOrder[i];
01228           array_insert_last(bdd_t *, nonAppearingVarBddArray,
01229                             bdd_dup(colInfo[col].data.col.var));
01230         }
01231       }
01232       qVarPos = nActiveCols - 1;
01233       if (qVarPos >= 0) {
01234         col = colOrder[qVarPos];
01235         while (colInfo[col].gNum == 0) {
01236           array_insert_last(bdd_t *, nonAppearingVarBddArray,
01237                             bdd_dup(colInfo[col].data.col.var));
01238           if (qVarPos == 0)
01239             break;
01240           qVarPos--;
01241           col = colOrder[qVarPos];
01242         }
01243       }
01244     } else
01245       qVarPos = 0; /* to avoid warning */
01246     for (i = nActiveRows - 1; i >= 0; i--) {
01247       row = rowOrder[i];
01248       if (arraySmoothVarBddArrayPtr) {
01249         smoothVarBddArray = array_alloc(array_t *, 0);
01250         col = colOrder[qVarPos];
01251         while (rowInfo[colInfo[col].gMin].pos == i) {
01252           index = (int)bdd_top_var_id(colInfo[col].data.col.var);
01253           array_insert_last(bdd_t *, smoothVarBddArray,
01254                                 bdd_dup(colInfo[col].data.col.var));
01255           if (qVarPos == 0)
01256             break;
01257           qVarPos--;
01258           col = colOrder[qVarPos];
01259         }
01260         array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01261       }
01262       relation = bdd_dup(rowInfo[row].data.row.func);
01263       array_insert_last(bdd_t *, orderedArray, relation);
01264     }
01265 
01266     if (nRows > nActiveRows) {
01267       for (i = nActiveRows; i < nRows; i++) {
01268         row = rowOrder[i];
01269         relation = rowInfo[row].data.row.func;
01270         array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
01271         if (arraySmoothVarBddArrayPtr) {
01272           smoothVarBddArray = array_alloc(array_t *, 0);
01273           array_insert_last(array_t *, arraySmoothVarBddArray,
01274                             smoothVarBddArray);
01275         }
01276       }
01277     }
01278   } else {
01279     if (arraySmoothVarBddArrayPtr) {
01280       UpdateNonappearingNsVars(mddManager, nsVarBddArray, nActiveRows,
01281                                 rowInfo, rowOrder, nonAppearingVarBddArray);
01282     }
01283     if (nRows > nActiveRows) {
01284       for (i = nActiveRows; i < nRows; i++) {
01285         row = rowOrder[i];
01286         relation = rowInfo[row].data.row.func;
01287         array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
01288         if (arraySmoothVarBddArrayPtr) {
01289           smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
01290           rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
01291           array_insert_last(array_t *, arraySmoothVarBddArray,
01292                             smoothVarBddArray);
01293         }
01294       }
01295     }
01296     for (i = 0; i < nActiveRows; i++) {
01297       row = rowOrder[i];
01298       if (arraySmoothVarBddArrayPtr) {
01299         smoothVarBddArray = array_alloc(array_t *, 0);
01300         for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
01301           nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
01302           array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
01303         }
01304 
01305         s = colInfo[rowInfo[row].gMin].pos;
01306         t = colInfo[rowInfo[row].gMax].pos;
01307         for (j = s; j <= t; j++) {
01308           col = colOrder[j];
01309           if (colInfo[col].data.col.type == 2) {
01310             if (rowInfo[colInfo[col].gMax].pos == i) {
01311               array_insert_last(bdd_t *, smoothVarBddArray,
01312                                 bdd_dup(colInfo[col].data.col.var));
01313             }
01314           }
01315         }
01316         array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01317       }
01318       relation = bdd_dup(rowInfo[row].data.row.func);
01319       array_insert_last(bdd_t *, orderedArray, relation);
01320     }
01321   }
01322 
01323   *orderedRelationArrayPtr = orderedArray;
01324   if (arraySmoothVarBddArrayPtr)
01325     *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
01326 
01327   FreeSccList(sccHeadList);
01328 
01329   FREE(varPos);
01330   for (i = 0; i < nRows; i++) {
01331     if (xy[i])
01332       FREE(xy[i]);
01333   }
01334   FREE(xy);
01335   FREE(rowOrder);
01336   FREE(colOrder);
01337   for (i = 0; i < nRows; i++) {
01338     bdd_free(rowInfo[i].data.row.func);
01339     if (rowInfo[i].data.row.nsVarBddArray)
01340       array_free(rowInfo[i].data.row.nsVarBddArray);
01341   }
01342   FREE(rowInfo);
01343   FREE(colInfo);
01344 }
01345 
01346 
01356 float
01357 ImgMlpComputeLambda(mdd_manager *mddManager,
01358                     array_t *relationArray,
01359                     array_t *domainVarBddArray,
01360                     array_t *quantifyVarBddArray,
01361                     array_t *rangeVarBddArray,
01362                     Img_DirectionType direction,
01363                     int mode,
01364                     int asIs,
01365                     int *prevArea,
01366                     float *improvedLambda,
01367                     ImgTrmOption_t *option)
01368 {
01369   int           i, nRows, nCols, nActiveRows, nActiveCols;
01370   int           *rowOrder, *colOrder;
01371   RcInfo_t      *rowInfo, *colInfo;
01372   char          **xy;
01373   bdd_t         *relation, *var;
01374   int           *varPos;
01375   array_t       *psVarBddArray, *nsVarBddArray;
01376   int           index, nVars, nc;
01377   SccList_t     *sccHeadList, *sccList;
01378   float         lambda;
01379   int           area;
01380 
01381   nRows = array_n(relationArray);
01382   if (direction == Img_Forward_c)
01383     nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
01384   else
01385     nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
01386 
01387   if (nCols == 0) {
01388     if (improvedLambda) {
01389       *improvedLambda = 0.0;
01390       *prevArea = 0;
01391     }
01392     return(0.0);
01393   }
01394 
01395   xy = ALLOC(char *, nRows);
01396   for (i = 0; i < nRows; i++) {
01397     xy[i] = ALLOC(char, nCols);
01398     memset(xy[i], 0, sizeof(char) * nCols);
01399   }
01400 
01401   rowOrder = ALLOC(int, nRows);
01402   for (i = 0; i < nRows; i++)
01403     rowOrder[i] = i;
01404   colOrder = ALLOC(int, nCols);
01405   for (i = 0; i < nCols; i++)
01406     colOrder[i] = i;
01407 
01408   rowInfo = ALLOC(RcInfo_t, nRows);
01409   memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
01410   colInfo = ALLOC(RcInfo_t, nCols);
01411   memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
01412   nVars = bdd_num_vars(mddManager);
01413   varPos = ALLOC(int, nVars);
01414   memset(varPos, 0, sizeof(int) * nVars);
01415 
01416   for (i = 0; i < nRows; i++) {
01417     relation = array_fetch(bdd_t *, relationArray, i);
01418     rowInfo[i].data.row.func = bdd_dup(relation);
01419   }
01420 
01421   psVarBddArray = domainVarBddArray;
01422   nsVarBddArray = rangeVarBddArray;
01423   nc = 0;
01424   for (i = 0; i < array_n(psVarBddArray); i++) {
01425     var = array_fetch(bdd_t *, psVarBddArray, i);
01426     colInfo[nc].data.col.var = var;
01427     colInfo[nc].data.col.type = 1;
01428     index = (int)bdd_top_var_id(var);
01429     varPos[index] = nc;
01430     nc++;
01431   }
01432   for (i = 0; i < array_n(quantifyVarBddArray); i++) {
01433     var = array_fetch(bdd_t *, quantifyVarBddArray, i);
01434     colInfo[nc].data.col.var = var;
01435     colInfo[nc].data.col.type = 2;
01436     index = (int)bdd_top_var_id(var);
01437     varPos[index] = nc;
01438     nc++;
01439   }
01440 
01441   SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
01442            rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
01443            NIL(array_t), direction, option);
01444   if (nActiveRows == 0) {
01445     FREE(varPos);
01446     for (i = 0; i < nRows; i++) {
01447       if (xy[i])
01448         FREE(xy[i]);
01449     }
01450     FREE(xy);
01451     FREE(rowOrder);
01452     FREE(colOrder);
01453     for (i = 0; i < nRows; i++) {
01454       bdd_free(rowInfo[i].data.row.func);
01455       if (rowInfo[i].data.row.nsVarBddArray)
01456         array_free(rowInfo[i].data.row.nsVarBddArray);
01457     }
01458     FREE(rowInfo);
01459     FREE(colInfo);
01460 
01461     if (improvedLambda) {
01462       *improvedLambda = 0.0;
01463       *prevArea = 0;
01464     }
01465     return(0.0);
01466   }
01467   sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
01468                                 rowOrder, colOrder, rowInfo, colInfo,
01469                                 0, option);
01470   sccList = sccHeadList;
01471   while (sccList) {
01472     BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
01473                         rowOrder, colOrder, rowInfo, colInfo, option);
01474     sccList = sccList->next;
01475   }
01476 
01477   lambda = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01478                             rowInfo, colInfo, rowOrder, colOrder,
01479                             direction, mode, asIs, option);
01480 
01481   FreeSccList(sccHeadList);
01482 
01483   FREE(varPos);
01484   for (i = 0; i < nRows; i++) {
01485     if (xy[i])
01486       FREE(xy[i]);
01487   }
01488   FREE(xy);
01489   FREE(rowOrder);
01490   FREE(colOrder);
01491   for (i = 0; i < nRows; i++) {
01492     bdd_free(rowInfo[i].data.row.func);
01493     if (rowInfo[i].data.row.nsVarBddArray)
01494       array_free(rowInfo[i].data.row.nsVarBddArray);
01495   }
01496   FREE(rowInfo);
01497   FREE(colInfo);
01498 
01499   if (option->mlpLambdaMode == 0)
01500     area = nActiveRows * nActiveCols;
01501   else
01502     area = nActiveRows * nCols;
01503   if (improvedLambda) {
01504     if (*prevArea)
01505       *improvedLambda = lambda * (float)area / (*prevArea);
01506     else
01507       *improvedLambda = 0.0;
01508     *prevArea = area;
01509   }
01510   return(lambda);
01511 }
01512 
01513 
01523 void
01524 ImgMlpGetQuantificationSchedule(mdd_manager *mddManager,
01525                         array_t *relationArray,
01526                         array_t *domainVarBddArray,
01527                         array_t *quantifyVarBddArray,
01528                         array_t *rangeVarBddArray,
01529                         array_t **clusteredRelationArrayPtr,
01530                         array_t **arraySmoothVarBddArrayPtr,
01531                         Img_DirectionType direction,
01532                         ImgTrmOption_t *option)
01533 {
01534   int           i, j, nRows, nCols, nActiveRows, nActiveCols;
01535   int           *rowOrder, *colOrder;
01536   RcInfo_t      *rowInfo, *colInfo;
01537   char          **xy;
01538   bdd_t         *relation, *var, *nsVar;
01539   int           *varPos;
01540   array_t       *psVarBddArray, *nsVarBddArray;
01541   int           index, nVars, nc;
01542   array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
01543   int           qVarPos, row, col, s, t;
01544   array_t       *nonAppearingVarBddArray;
01545   array_t       *clusteredRelationArray;
01546 
01547   nRows = array_n(relationArray);
01548   if (direction == Img_Forward_c)
01549     nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
01550   else
01551     nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
01552 
01553   xy = ALLOC(char *, nRows);
01554   for (i = 0; i < nRows; i++) {
01555     xy[i] = ALLOC(char, nCols);
01556     memset(xy[i], 0, sizeof(char) * nCols);
01557   }
01558 
01559   rowOrder = ALLOC(int, nRows);
01560   for (i = 0; i < nRows; i++)
01561     rowOrder[i] = i;
01562   colOrder = ALLOC(int, nCols);
01563   for (i = 0; i < nCols; i++)
01564     colOrder[i] = i;
01565 
01566   rowInfo = ALLOC(RcInfo_t, nRows);
01567   memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
01568   colInfo = ALLOC(RcInfo_t, nCols);
01569   memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
01570   nVars = bdd_num_vars(mddManager);
01571   varPos = ALLOC(int, nVars);
01572   memset(varPos, 0, sizeof(int) * nVars);
01573 
01574   psVarBddArray = domainVarBddArray;
01575   nsVarBddArray = rangeVarBddArray;
01576   if (direction == Img_Forward_c) {
01577     for (i = 0; i < nRows; i++) {
01578       relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
01579       rowInfo[i].data.row.func = bdd_dup(relation);
01580     }
01581   } else {
01582     for (i = 0; i < nRows; i++) {
01583       relation = array_fetch(bdd_t *, relationArray, i);
01584       rowInfo[i].data.row.func = bdd_dup(relation);
01585     }
01586   }
01587   nc = 0;
01588   for (i = 0; i < array_n(psVarBddArray); i++) {
01589     var = array_fetch(bdd_t *, psVarBddArray, i);
01590     colInfo[nc].data.col.var = var;
01591     colInfo[nc].data.col.type = 1;
01592     index = (int)bdd_top_var_id(var);
01593     varPos[index] = nc;
01594     nc++;
01595   }
01596   for (i = 0; i < array_n(quantifyVarBddArray); i++) {
01597     var = array_fetch(bdd_t *, quantifyVarBddArray, i);
01598     colInfo[nc].data.col.var = var;
01599     colInfo[nc].data.col.type = 2;
01600     index = (int)bdd_top_var_id(var);
01601     varPos[index] = nc;
01602     nc++;
01603   }
01604 
01605   nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
01606   SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
01607            rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
01608            nonAppearingVarBddArray, direction, option);
01609   SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
01610 
01611   clusteredRelationArray = array_alloc(mdd_t *, 0);
01612   arraySmoothVarBddArray = array_alloc(array_t *, 0);
01613   if (direction == Img_Forward_c) {
01614     if (nCols > nActiveCols) {
01615       for (i = nActiveCols; i < nCols; i++) {
01616         col = colOrder[i];
01617         array_insert_last(bdd_t *, nonAppearingVarBddArray,
01618                           bdd_dup(colInfo[col].data.col.var));
01619       }
01620     }
01621     qVarPos = nActiveCols - 1;
01622     if (qVarPos >= 0) {
01623       col = colOrder[qVarPos];
01624       while (colInfo[col].gNum == 0) {
01625         array_insert_last(bdd_t *, nonAppearingVarBddArray,
01626                           bdd_dup(colInfo[col].data.col.var));
01627         if (qVarPos == 0)
01628           break;
01629         qVarPos--;
01630         col = colOrder[qVarPos];
01631       }
01632     }
01633     array_insert_last(array_t *, arraySmoothVarBddArray,
01634                         nonAppearingVarBddArray);
01635     for (i = nActiveRows - 1; i >= 0; i--) {
01636       row = rowOrder[i];
01637       smoothVarBddArray = array_alloc(array_t *, 0);
01638       if (rowInfo[row].gNum > 0) {
01639         col = colOrder[qVarPos];
01640         while (rowInfo[colInfo[col].gMin].pos == i) {
01641           index = (int)bdd_top_var_id(colInfo[col].data.col.var);
01642           array_insert_last(bdd_t *, smoothVarBddArray,
01643                                 bdd_dup(colInfo[col].data.col.var));
01644           if (qVarPos == 0)
01645             break;
01646           qVarPos--;
01647           col = colOrder[qVarPos];
01648         }
01649       }
01650       array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01651       relation = bdd_dup(rowInfo[row].data.row.func);
01652       array_insert_last(bdd_t *, clusteredRelationArray, relation);
01653     }
01654     if (nRows > nActiveRows) {
01655       for (i = nActiveRows; i < nRows; i++) {
01656         row = rowOrder[i];
01657         smoothVarBddArray = array_alloc(array_t *, 0);
01658         array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01659         relation = bdd_dup(rowInfo[row].data.row.func);
01660         array_insert_last(bdd_t *, clusteredRelationArray, relation);
01661       }
01662     }
01663   } else {
01664     array_insert_last(array_t *, arraySmoothVarBddArray,
01665                         nonAppearingVarBddArray);
01666     if (nRows > nActiveRows) {
01667       for (i = nActiveRows; i < nRows; i++) {
01668         row = rowOrder[i];
01669         smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
01670         rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
01671         array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01672         relation = bdd_dup(rowInfo[row].data.row.func);
01673         array_insert_last(bdd_t *, clusteredRelationArray, relation);
01674       }
01675     }
01676     for (i = 0; i < nActiveRows; i++) {
01677       row = rowOrder[i];
01678       smoothVarBddArray = array_alloc(array_t *, 0);
01679       for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
01680         nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
01681         array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
01682       }
01683       if (rowInfo[row].gNum > 0) {
01684         s = colInfo[rowInfo[row].gMin].pos;
01685         t = colInfo[rowInfo[row].gMax].pos;
01686         for (j = s; j <= t; j++) {
01687           col = colOrder[j];
01688           if (colInfo[col].data.col.type == 2) {
01689             if (rowInfo[colInfo[col].gMax].pos == i) {
01690               array_insert_last(bdd_t *, smoothVarBddArray,
01691                                 bdd_dup(colInfo[col].data.col.var));
01692             }
01693           }
01694         }
01695       }
01696       array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
01697       relation = bdd_dup(rowInfo[row].data.row.func);
01698       array_insert_last(bdd_t *, clusteredRelationArray, relation);
01699     }
01700   }
01701 
01702   FREE(varPos);
01703   for (i = 0; i < nRows; i++) {
01704     if (xy[i])
01705       FREE(xy[i]);
01706   }
01707   FREE(xy);
01708   FREE(rowOrder);
01709   FREE(colOrder);
01710   for (i = 0; i < nRows; i++) {
01711     bdd_free(rowInfo[i].data.row.func);
01712     if (rowInfo[i].data.row.nsVarBddArray)
01713       array_free(rowInfo[i].data.row.nsVarBddArray);
01714   }
01715   FREE(rowInfo);
01716   FREE(colInfo);
01717 
01718   *clusteredRelationArrayPtr = clusteredRelationArray;
01719   *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
01720 }
01721 
01722 
01732 void
01733 ImgMlpPrintDependenceMatrix(mdd_manager *mddManager,
01734                         array_t *relationArray,
01735                         array_t *domainVarBddArray,
01736                         array_t *quantifyVarBddArray,
01737                         array_t *rangeVarBddArray,
01738                         Img_DirectionType direction,
01739                         int printFlag, FILE *fout,
01740                         ImgTrmOption_t *option)
01741 {
01742   int           i, nRows, nCols, nActiveRows, nActiveCols;
01743   int           *rowOrder, *colOrder;
01744   RcInfo_t      *rowInfo, *colInfo;
01745   char          **xy;
01746   bdd_t         *relation, *var;
01747   int           *varPos;
01748   array_t       *psVarBddArray, *nsVarBddArray;
01749   int           index, nVars, nc;
01750   float         lambda1, lambda2, lambda3;
01751 
01752   nRows = array_n(relationArray);
01753   if (direction == Img_Forward_c)
01754     nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
01755   else
01756     nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
01757 
01758   xy = ALLOC(char *, nRows);
01759   for (i = 0; i < nRows; i++) {
01760     xy[i] = ALLOC(char, nCols);
01761     memset(xy[i], 0, sizeof(char) * nCols);
01762   }
01763 
01764   rowOrder = ALLOC(int, nRows);
01765   for (i = 0; i < nRows; i++)
01766     rowOrder[i] = i;
01767   colOrder = ALLOC(int, nCols);
01768   for (i = 0; i < nCols; i++)
01769     colOrder[i] = i;
01770 
01771   rowInfo = ALLOC(RcInfo_t, nRows);
01772   memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
01773   colInfo = ALLOC(RcInfo_t, nCols);
01774   memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
01775   nVars = bdd_num_vars(mddManager);
01776   varPos = ALLOC(int, nVars);
01777   memset(varPos, 0, sizeof(int) * nVars);
01778 
01779   psVarBddArray = domainVarBddArray;
01780   nsVarBddArray = rangeVarBddArray;
01781   if (direction == Img_Forward_c) {
01782     for (i = 0; i < nRows; i++) {
01783       relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
01784       rowInfo[i].data.row.func = bdd_dup(relation);
01785     }
01786   } else {
01787     for (i = 0; i < nRows; i++) {
01788       relation = array_fetch(bdd_t *, relationArray, i);
01789       rowInfo[i].data.row.func = bdd_dup(relation);
01790     }
01791   }
01792   nc = 0;
01793   for (i = 0; i < array_n(psVarBddArray); i++) {
01794     var = array_fetch(bdd_t *, psVarBddArray, i);
01795     colInfo[nc].data.col.var = var;
01796     colInfo[nc].data.col.type = 1;
01797     index = (int)bdd_top_var_id(var);
01798     varPos[index] = nc;
01799     nc++;
01800   }
01801   for (i = 0; i < array_n(quantifyVarBddArray); i++) {
01802     var = array_fetch(bdd_t *, quantifyVarBddArray, i);
01803     colInfo[nc].data.col.var = var;
01804     colInfo[nc].data.col.type = 2;
01805     index = (int)bdd_top_var_id(var);
01806     varPos[index] = nc;
01807     nc++;
01808   }
01809 
01810   SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
01811            rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
01812            NIL(array_t), direction, option);
01813   SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
01814 
01815   if (printFlag) {
01816     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
01817                 rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
01818   }
01819   if (fout) {
01820     WriteMatrix(fout, xy, nActiveRows, nActiveCols, rowOrder, colOrder,
01821                 rowInfo, colInfo);
01822   }
01823   lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01824                                 rowInfo, colInfo, rowOrder, colOrder,
01825                                 direction, 0, 0, option);
01826   lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01827                                 rowInfo, colInfo, rowOrder, colOrder,
01828                                 direction, 1, 0, option);
01829   lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
01830                                 rowInfo, colInfo, rowOrder, colOrder,
01831                                 direction, 2, 0, option);
01832   fprintf(vis_stdout, "Lambda = %f (%f, %f)\n", lambda1, lambda2, lambda3);
01833 
01834   FREE(varPos);
01835   for (i = 0; i < nRows; i++) {
01836     if (xy[i])
01837       FREE(xy[i]);
01838   }
01839   FREE(xy);
01840   FREE(rowOrder);
01841   FREE(colOrder);
01842   for (i = 0; i < nRows; i++) {
01843     bdd_free(rowInfo[i].data.row.func);
01844     if (rowInfo[i].data.row.nsVarBddArray)
01845       array_free(rowInfo[i].data.row.nsVarBddArray);
01846   }
01847   FREE(rowInfo);
01848   FREE(colInfo);
01849 }
01850 
01851 
01861 void
01862 ImgMlpWriteClusterFile(FILE *fout,
01863                         mdd_manager *mddManager,
01864                         array_t *relationArray,
01865                         array_t *psVarBddArray,
01866                         array_t *nsVarBddArray)
01867 {
01868   int           i, j, k, nVars;
01869   int           bddId, mddId, id, index;
01870   mdd_t         *relation;
01871   mdd_t         *psVar, *nsVar, **nsVars, **ns2ps;
01872   array_t       *supportBddIdArray, *bddIdArray;
01873   char          *name;
01874   int           count;
01875 
01876   nVars = bdd_num_vars(mddManager);
01877   nsVars = ALLOC(bdd_t *, nVars);
01878   memset(nsVars, 0, sizeof(bdd_t *) * nVars);
01879   ns2ps = ALLOC(bdd_t *, nVars);
01880   memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
01881 
01882   for (i = 0; i < array_n(nsVarBddArray); i++) {
01883     psVar = array_fetch(bdd_t *, psVarBddArray, i);
01884     nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
01885     index = (int)bdd_top_var_id(nsVar);
01886     nsVars[index] = nsVar;
01887     ns2ps[index] = psVar;
01888   }
01889 
01890   count = 0;
01891   for (i = 0; i < array_n(relationArray); i++) {
01892     relation = array_fetch(mdd_t *, relationArray, i);
01893     supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
01894     psVar = NULL;
01895     for (j = 0; j < array_n(supportBddIdArray); j++) {
01896       bddId = array_fetch(int, supportBddIdArray, j);
01897       psVar = ns2ps[bddId];
01898       if (psVar) {
01899         break;
01900       }
01901     }
01902     if (psVar) {
01903       if (count == 0)
01904         fprintf(fout, "CLUSTER[%d] {\n", count);
01905       else
01906         fprintf(fout, "\nCLUSTER[%d] {\n", count);
01907       count++;
01908     }
01909     for (j = 0; j < array_n(supportBddIdArray); j++) {
01910       bddId = array_fetch(int, supportBddIdArray, j);
01911       psVar = ns2ps[bddId];
01912       if (psVar) {
01913         name = mdd_read_var_name(psVar);
01914         nsVar = nsVars[bddId];
01915         mddId = mdd_read_mdd_id(nsVar);
01916         bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
01917         for (k = 0; k < array_n(bddIdArray); k++) {
01918           id = array_fetch(int, bddIdArray, k);
01919           if (id == bddId) {
01920             fprintf(fout, "%s %d\n", name, k);
01921             break;
01922           }
01923         }
01924         array_free(bddIdArray);
01925       }
01926     }
01927     array_free(supportBddIdArray);
01928     fprintf(fout, "}\n");
01929   }
01930 
01931   FREE(nsVars);
01932   FREE(ns2ps);
01933 }
01934 
01935 
01936 
01937 
01947 void
01948 ImgMlpReadClusterFile(FILE *fin, mdd_manager *mddManager,
01949                         ImgFunctionData_t *functionData,
01950                         array_t *relationArray,
01951                         array_t *psVarBddArray,
01952                         array_t *nsVarBddArray,
01953                         array_t *quantifyVarBddArray,
01954                         Img_DirectionType direction,
01955                         array_t **clusteredRelationArrayPtr,
01956                         array_t **arraySmoothVarBddArrayPtr,
01957                         ImgTrmOption_t *option)
01958 {
01959   array_t       *clusteredRelationArray, *newRelationArray;
01960   array_t       *arraySmoothVarBddArray;
01961   int           i, j, k, nVars;
01962   long          bddId;
01963   int           mddId, id, index;
01964   mdd_t         *relation, *cluster, *newCluster;
01965   mdd_t         *var, *psVar, *nsVar, **nsVars, **ns2ps;
01966   array_t       *supportBddIdArray, *bddIdArray;
01967   char          *name;
01968   LatchList_t   **latchList;
01969   st_table      *intermediateTable, *nameTable, *quantifyVarsTable, *idTable;
01970   int           nRelVars, relBddId, relMddId;
01971   mdd_t         *relVar;
01972   char          *resolved;
01973   char          line[512], nameArray[512];
01974   st_generator  *stGen1, *stGen2;
01975 
01976   nVars = bdd_num_vars(mddManager);
01977   nsVars = ALLOC(bdd_t *, nVars);
01978   memset(nsVars, 0, sizeof(bdd_t *) * nVars);
01979   ns2ps = ALLOC(bdd_t *, nVars);
01980   memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
01981   latchList = ALLOC(LatchList_t *, nVars);
01982   memset(latchList, 0, sizeof(LatchList_t *) * nVars);
01983   resolved = ALLOC(char, nVars);
01984   memset(resolved, 0, sizeof(char) * nVars);
01985 
01986   quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
01987   for (i = 0; i < array_n(functionData->quantifyBddVars); i++) {
01988     var = array_fetch(mdd_t *, functionData->quantifyBddVars, i);
01989     index = (int)bdd_top_var_id(var);
01990     st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
01991   }
01992 
01993   nameTable = st_init_table(strcmp, st_strhash);
01994   for (i = 0; i < array_n(nsVarBddArray); i++) {
01995     psVar = array_fetch(bdd_t *, psVarBddArray, i);
01996     nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
01997     index = (int)bdd_top_var_id(nsVar);
01998     nsVars[index] = nsVar;
01999     ns2ps[index] = psVar;
02000     name = mdd_read_var_name(psVar);
02001     mddId = mdd_read_mdd_id(nsVar);
02002     st_insert(nameTable, name, (char *)(long)mddId);
02003 
02004     index = (int)bdd_top_var_id(psVar);
02005     st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
02006   }
02007 
02008   i = 0;
02009   st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
02010     printf("[%d] name = %s mdd = %d\n", i, name, mddId);
02011     i++;
02012   }
02013 
02014   intermediateTable = st_init_table(st_ptrcmp, st_ptrhash);
02015   for (i = 0; i < array_n(relationArray); i++) {
02016     relation = array_fetch(mdd_t *, relationArray, i);
02017     supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
02018     nRelVars = 0;
02019     psVar = NIL(bdd_t);
02020     nsVar = NIL(bdd_t);
02021     relVar = NIL(bdd_t);
02022     relBddId = -1;
02023     relMddId = -1;
02024     idTable = st_init_table(st_numcmp, st_numhash);
02025     for (j = 0; j < array_n(supportBddIdArray); j++) {
02026       bddId = (long) array_fetch(int, supportBddIdArray, j);
02027       if (st_lookup(quantifyVarsTable, (char *)bddId, NIL(char *)))
02028         continue;
02029       psVar = ns2ps[bddId];
02030       if (psVar) {
02031         if (relVar) {
02032           bdd_free(relVar);
02033           relVar = NIL(bdd_t);
02034         }
02035         nsVar = nsVars[bddId];
02036         relMddId = mdd_read_mdd_id(nsVar);
02037         relBddId = (int) bddId;
02038         break;
02039       } else {
02040         if (nRelVars > 0) {
02041           if (relVar)
02042             bdd_free(relVar);
02043         }
02044         relVar = bdd_var_with_index(mddManager, (int) bddId);
02045         relMddId = mdd_read_mdd_id(relVar);
02046         relBddId = (int) bddId;
02047         name = mdd_read_var_name(relVar);
02048         st_insert(nameTable, name, (char *)(long)relMddId);
02049         st_insert(idTable, (char *)bddId, NIL(char));
02050         if (nRelVars >= 1) {
02051           bdd_free(relVar);
02052           relVar = NIL(bdd_t);
02053         }
02054         nRelVars++;
02055       }
02056     }
02057     array_free(supportBddIdArray);
02058     if (nsVar || relVar) {
02059       bddId = (int) relBddId;
02060       mddId = relMddId;
02061 
02062       if (relVar)
02063         resolved[bddId] = 1;
02064 
02065       bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
02066       for (k = 0; k < array_n(bddIdArray); k++) {
02067         id = array_fetch(int, bddIdArray, k);
02068         if (id == bddId) {
02069           if (latchList[mddId]) {
02070             if (latchList[mddId]->number == 1) {
02071               latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
02072               st_insert(latchList[mddId]->table,
02073                         (char *)(long)latchList[mddId]->bddId,
02074                         (char *)latchList[mddId]->relation);
02075             }
02076             st_insert(latchList[mddId]->table, (char *)bddId,
02077                       (char *)relation);
02078           } else {
02079             latchList[mddId] = ALLOC(LatchList_t, 1);
02080             latchList[mddId]->bddId = (int) bddId;
02081             latchList[mddId]->relation = relation;
02082             latchList[mddId]->number = 1;
02083             latchList[mddId]->table = NIL(st_table);
02084           }
02085           break;
02086         }
02087       }
02088       array_free(bddIdArray);
02089       st_free_table(idTable);
02090     } else {
02091       st_insert(intermediateTable, (char *)relation, (char *)idTable);
02092     }
02093   }
02094 
02095   i = 0;
02096   st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
02097     printf("[%d] name = %s mdd = %d\n", i, name, mddId);
02098     i++;
02099   }
02100 
02101   while (intermediateTable->num_entries > 0) {
02102     st_foreach_item(intermediateTable, stGen1, &relation, &idTable) {
02103       st_foreach_item(idTable, stGen2, &bddId, NIL(char *)) {
02104         if (resolved[bddId])
02105           st_delete(idTable, &bddId, NIL(char *));
02106       }
02107       if (idTable->num_entries == 1) {
02108         st_foreach_item(idTable, stGen2, &bddId, NULL);
02109         relVar = bdd_var_with_index(mddManager, (int) bddId);
02110         mddId = mdd_read_mdd_id(relVar);
02111         mdd_free(relVar);
02112 
02113         st_delete(intermediateTable, &relation, NULL);
02114 
02115         bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
02116         for (k = 0; k < array_n(bddIdArray); k++) {
02117           id = array_fetch(int, bddIdArray, k);
02118           if (id == bddId) {
02119             if (latchList[mddId]) {
02120               if (latchList[mddId]->number == 1) {
02121                 latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
02122                 st_insert(latchList[mddId]->table,
02123                           (char *)(long)latchList[mddId]->bddId,
02124                           (char *)latchList[mddId]->relation);
02125               }
02126               st_insert(latchList[mddId]->table, (char *)bddId,
02127                         (char *)relation);
02128             } else {
02129               latchList[mddId] = ALLOC(LatchList_t, 1);
02130               latchList[mddId]->bddId = (int) bddId;
02131               latchList[mddId]->relation = relation;
02132               latchList[mddId]->number = 1;
02133               latchList[mddId]->table = NIL(st_table);
02134             }
02135             break;
02136           }
02137         }
02138         array_free(bddIdArray);
02139       }
02140     }
02141   }
02142   st_free_table(intermediateTable);
02143 
02144   i = 0;
02145   st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
02146     printf("[%d] name = %s mdd = %d\n", i, name, mddId);
02147     i++;
02148   }
02149 
02150   cluster = NIL(mdd_t);
02151   clusteredRelationArray = array_alloc(mdd_t *, 0);
02152   while (fgets(line, 512, fin)) {
02153     if (line[0] == '\n' || line[0] == '#')
02154       continue;
02155     if (strncmp(line, "CLUSTER", 7) == 0)
02156       cluster = mdd_one(mddManager);
02157     else if (strncmp(line, "}", 1) == 0)
02158       array_insert_last(mdd_t *, clusteredRelationArray, cluster);
02159     else {
02160       sscanf(line, "%s %d", nameArray, &id);
02161       if (st_lookup_int(nameTable, nameArray, &mddId) == 0)
02162         assert(0);
02163       if (latchList[mddId]) {
02164         if (latchList[mddId]->table) {
02165           bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
02166           assert(id < array_n(bddIdArray));
02167           bddId = (long) array_fetch(int, bddIdArray, id);
02168           if (st_lookup(latchList[mddId]->table, (char *)bddId, &relation)) {
02169             latchList[mddId]->number--;
02170             if (latchList[mddId]->number == 0) {
02171               st_free_table(latchList[mddId]->table);
02172               FREE(latchList[mddId]);
02173               latchList[mddId] = NIL(LatchList_t);
02174             }
02175           } else
02176             assert(0);
02177         } else {
02178           relation = latchList[mddId]->relation;
02179           FREE(latchList[mddId]);
02180           latchList[mddId] = NIL(LatchList_t);
02181         }
02182         newCluster = bdd_and(cluster, relation, 1, 1);
02183         mdd_free(cluster);
02184         cluster = newCluster;
02185       } else
02186         assert(0);
02187     }
02188   }
02189 
02190   for (i = 0; i < nVars; i++) {
02191     if (latchList[i]) {
02192       if (latchList[i]->table) {
02193         st_foreach_item(latchList[i]->table, stGen1, &bddId, &relation) {
02194           cluster = bdd_dup(relation);
02195           array_insert_last(mdd_t *, clusteredRelationArray, cluster);
02196         }
02197         st_free_table(latchList[i]->table);
02198       } else {
02199         cluster = bdd_dup(latchList[i]->relation);
02200         array_insert_last(mdd_t *, clusteredRelationArray, cluster);
02201       }
02202       FREE(latchList[i]);
02203     }
02204   }
02205 
02206   FREE(nsVars);
02207   FREE(ns2ps);
02208   FREE(resolved);
02209   FREE(latchList);
02210 
02211   st_free_table(nameTable);
02212   st_free_table(quantifyVarsTable);
02213 
02214   if (arraySmoothVarBddArrayPtr) {
02215     ImgMlpGetQuantificationSchedule(mddManager,
02216                 clusteredRelationArray, psVarBddArray, quantifyVarBddArray,
02217                 nsVarBddArray, &newRelationArray, &arraySmoothVarBddArray,
02218                 direction, option);
02219     mdd_array_free(clusteredRelationArray);
02220     clusteredRelationArray = newRelationArray;
02221   } else
02222     arraySmoothVarBddArray = NIL(array_t);
02223 
02224   *clusteredRelationArrayPtr = clusteredRelationArray;
02225   *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
02226 }
02227 
02228 
02229 /*---------------------------------------------------------------------------*/
02230 /* Definition of static functions                                            */
02231 /*---------------------------------------------------------------------------*/
02232 
02242 static void
02243 SetupMlp(mdd_manager *mddManager,
02244          char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
02245          RcInfo_t *rowInfo, RcInfo_t *colInfo, int *varPos,
02246          array_t *nsVarBddArray, int *nActiveRows, int *nActiveCols,
02247          array_t *nonAppearingVarBddArray,
02248          Img_DirectionType direction, ImgTrmOption_t *option)
02249 {
02250   int           i, j, x, y, s, t;
02251   int           row, col, otherCol, nr, nc, index;
02252   long          initialTime, finalTime;
02253   bdd_t         *relation, *nsVar;
02254   array_t       *supportArray, *localVarBddArray;
02255   int           support;
02256   array_t       **arrayLocalVarBddArray;
02257   float         lambda1, lambda2, lambda3;
02258   bdd_t         **nsVarArray;
02259   int           nVars;
02260 
02261   if (option->mlpVerbosity >= 2)
02262     initialTime = util_cpu_time();
02263   else
02264     initialTime = 0;
02265 
02266   nVars = bdd_num_vars(mddManager);
02267   nsVarArray = ALLOC(bdd_t *, nVars);
02268   memset(nsVarArray, 0, sizeof(bdd_t *) * nVars);
02269   for (i = 0; i < array_n(nsVarBddArray); i++) {
02270     nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
02271     index = (int)bdd_top_var_id(nsVar);
02272     nsVarArray[index] = nsVar;
02273   }
02274 
02275   for (i = 0; i < nRows; i++) {
02276     relation = rowInfo[i].data.row.func;
02277     rowInfo[i].data.row.nsVarBddArray = array_alloc(bdd_t *, 0);
02278     supportArray = mdd_get_bdd_support_ids(mddManager, relation);
02279     for (j = 0; j < array_n(supportArray); j++) {
02280       support = array_fetch(int, supportArray, j);
02281       nsVar = nsVarArray[support];
02282       if (nsVar) {
02283         array_insert_last(bdd_t *, rowInfo[i].data.row.nsVarBddArray, nsVar);
02284         if (varPos[support])
02285           xy[i][varPos[support]] = 1;
02286         else {
02287           index = (int)bdd_top_var_id(colInfo[0].data.col.var);
02288           if (index == support)
02289             xy[i][varPos[support]] = 1;
02290         }
02291       } else
02292         xy[i][varPos[support]] = 1;
02293     }
02294     array_free(supportArray);
02295   }
02296   FREE(nsVarArray);
02297 
02298   for (x = 0; x < nRows; x++) {
02299     rowInfo[x].gMin = nCols;
02300     rowInfo[x].gMax = -1;
02301     rowInfo[x].pos = x;
02302     rowInfo[x].prevG = -1;
02303     rowInfo[x].nextG = nCols;
02304   }
02305   for (y = 0; y < nCols; y++) {
02306     colInfo[y].gMin = nRows;
02307     colInfo[y].gMax = -1;
02308     colInfo[y].pos = y;
02309     colInfo[y].prevG = -1;
02310     colInfo[y].nextG = nRows;
02311   }
02312 
02313   for (x = 0; x < nRows; x++) {
02314     for (y = 0; y < nCols; y++) {
02315       if (xy[x][y]) {
02316         if (x < colInfo[y].gMin)
02317           colInfo[y].gMin = x;
02318         if (x > colInfo[y].gMax)
02319           colInfo[y].gMax = x;
02320         if (y < rowInfo[x].gMin)
02321           rowInfo[x].gMin = y;
02322         if (y > rowInfo[x].gMax)
02323           rowInfo[x].gMax = y;
02324         rowInfo[x].gNum++;
02325         colInfo[y].gNum++;
02326       }
02327     }
02328   }
02329 
02330   nc = nCols;
02331   arrayLocalVarBddArray = ALLOC(array_t *, nRows);
02332   memset(arrayLocalVarBddArray, 0, sizeof(array_t *) * nRows);
02333   for (y = 0; y < nc; y++) {
02334     col = colOrder[y];
02335     if (colInfo[col].data.col.type == 2 && colInfo[col].gNum == 1) {
02336       row = colInfo[col].gMin;
02337       rowInfo[row].gNum--;
02338       if (rowInfo[row].gNum == 1) {
02339         if (rowInfo[row].gMin == col) {
02340           rowInfo[row].gMin = rowInfo[row].gMax;
02341           rowInfo[row].lMin = rowInfo[row].lMax;
02342         } else {
02343           rowInfo[row].gMax = rowInfo[row].gMin;
02344           rowInfo[row].lMax = rowInfo[row].lMin;
02345         }
02346       } else if (rowInfo[row].gNum > 1) {
02347         if (rowInfo[row].gMin == col) {
02348           s = colInfo[rowInfo[row].gMin].pos;
02349           t = colInfo[rowInfo[row].gMax].pos;
02350           for (j = s + 1; j <= t; j++) {
02351             otherCol = colOrder[j];
02352             if (xy[row][otherCol]) {
02353               rowInfo[row].gMin = otherCol;
02354               rowInfo[row].lMin = otherCol;
02355               break;
02356             }
02357           }
02358         } else if (rowInfo[row].gMax == col) {
02359           s = colInfo[rowInfo[row].gMin].pos;
02360           t = colInfo[rowInfo[row].gMax].pos;
02361           for (j = t - 1; j >= s; j--) {
02362             otherCol = colOrder[j];
02363             if (xy[row][otherCol]) {
02364               rowInfo[row].gMax = otherCol;
02365               rowInfo[row].lMax = otherCol;
02366               break;
02367             }
02368           }
02369         }
02370       }
02371 
02372       for (j = y; j < nc - 1; j++) {
02373         colOrder[j] = colOrder[j + 1];
02374         colInfo[colOrder[j]].pos = j;
02375       }
02376       colOrder[nc - 1] = col;
02377       colInfo[col].pos = nc - 1;
02378 
02379       nc--;
02380       y--;
02381 
02382       if (!arrayLocalVarBddArray[row])
02383         arrayLocalVarBddArray[row] = array_alloc(bdd_t *, 0);
02384       array_insert_last(bdd_t *, arrayLocalVarBddArray[row],
02385                         colInfo[col].data.col.var);
02386     }
02387   }
02388 
02389   if (direction == Img_Backward_c) {
02390     long        lindex;
02391     st_table    *unusedNsTable;
02392     st_generator *gen;
02393 
02394     unusedNsTable = st_init_table(st_numcmp, st_numhash);
02395     for (i = 0; i < array_n(nsVarBddArray); i++) {
02396       nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
02397       lindex = (long) bdd_top_var_id(nsVar);
02398       st_insert(unusedNsTable, (char *)lindex, (char *)nsVar);
02399     }
02400     for (i = 0; i < nRows; i++) {
02401       for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
02402         nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
02403         lindex = (long) bdd_top_var_id(nsVar);
02404         st_delete(unusedNsTable, &lindex, NULL);
02405       }
02406     }
02407     st_foreach_item(unusedNsTable, gen, &lindex, &nsVar) {
02408       array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
02409     }
02410     st_free_table(unusedNsTable);
02411   }
02412 
02413   for (i = 0; i < nRows; i++) {
02414     localVarBddArray = arrayLocalVarBddArray[i];
02415     if (localVarBddArray) {
02416       relation = bdd_smooth(rowInfo[i].data.row.func, localVarBddArray);
02417       if (nonAppearingVarBddArray && direction == Img_Backward_c &&
02418           bdd_is_tautology(relation, 1)) {
02419           for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
02420             nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
02421             array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
02422           }
02423       }
02424       bdd_free(rowInfo[i].data.row.func);
02425       rowInfo[i].data.row.func = relation;
02426       UpdateDisapearingPsVars(mddManager, xy, nRows, nCols,
02427                         rowOrder, colOrder, rowInfo, colInfo,
02428                         i, option);
02429       if (localVarBddArray)
02430         array_free(localVarBddArray);
02431     }
02432   }
02433   FREE(arrayLocalVarBddArray);
02434 
02435   for (y = 0; y < nc; y++) {
02436     col = colOrder[y];
02437     if (colInfo[col].gNum == 0) {
02438       if (nonAppearingVarBddArray &&
02439           direction == Img_Forward_c && colInfo[col].data.col.type == 1) {
02440         array_insert_last(bdd_t *, nonAppearingVarBddArray,
02441                           bdd_dup(colInfo[col].data.col.var));
02442       }
02443       for (j = y; j < nc - 1; j++) {
02444         colOrder[j] = colOrder[j + 1];
02445         colInfo[colOrder[j]].pos = j;
02446       }
02447       colOrder[nc - 1] = col;
02448       colInfo[col].pos = nc - 1;
02449       nc--;
02450       y--;
02451     }
02452   }
02453 
02454   nr = nRows;
02455   for (x = 0; x < nr; x++) {
02456     row = rowOrder[x];
02457     if (rowInfo[row].gNum == 0) {
02458       for (i = x; i < nr - 1; i++) {
02459         rowOrder[i] = rowOrder[i + 1];
02460         rowInfo[rowOrder[i]].pos = i;
02461       }
02462       rowOrder[nr - 1] = row;
02463       rowInfo[row].pos = nr - 1;
02464       nr--;
02465       x--;
02466     }
02467   }
02468 
02469   for (x = 0; x < nr; x++) {
02470     row = rowOrder[x];
02471     rowInfo[row].lMin = rowInfo[row].gMin;
02472     rowInfo[row].lMax = rowInfo[row].gMax;
02473     rowInfo[row].lNum = rowInfo[row].gNum;
02474     if (nc != nCols && rowInfo[row].nextG == nCols)
02475       rowInfo[row].nextG = nc;
02476   }
02477   for (y = 0; y < nc; y++) {
02478     col = colOrder[y];
02479     colInfo[col].lMin = colInfo[col].gMin;
02480     colInfo[col].lMax = colInfo[col].gMax;
02481     colInfo[col].lNum = colInfo[col].gNum;
02482     if (nr != nRows && colInfo[col].nextG == nRows)
02483       colInfo[col].nextG = nr;
02484   }
02485   if (option->mlpVerbosity >= 2) {
02486     finalTime = util_cpu_time();
02487     fprintf(vis_stdout, "time for setup = %10g\n",
02488            (double)(finalTime - initialTime) / 1000.0);
02489 
02490     lambda1 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
02491                                 rowOrder, colOrder, direction, 0, 0, option);
02492     lambda2 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
02493                                 rowOrder, colOrder, direction, 1, 0, option);
02494     lambda3 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
02495                                 rowOrder, colOrder, direction, 2, 0, option);
02496     fprintf(vis_stdout, "Initial Lambda = %f (%f, %f)\n",
02497             lambda1, lambda2, lambda3);
02498   }
02499 
02500   if (option->mlpDebug) {
02501     CheckMatrix(xy, NIL(SccList_t), nr, nc, rowInfo, colInfo,
02502                 rowOrder, colOrder, 0, nr - 1, 0, nc - 1, 1);
02503   }
02504 
02505   *nActiveRows = nr;
02506   *nActiveCols = nc;
02507 }
02508 
02509 
02519 static SccList_t *
02520 MlpDecomposeScc(mdd_manager *mddManager, char **xy, int nRows,
02521                 int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder,
02522                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
02523                 int clusteredFlag, ImgTrmOption_t *option)
02524 {
02525   int           i, j, x, y, size, nVars;
02526   int           startRow, startCol;
02527   int           nGroups, nChosen;
02528   int           row, col, otherRow;
02529   int           s1, t1, s2, t2;
02530   char          *rowFlag, *colFlag, *stackFlag;
02531   int           *stack;
02532   SccList_t     *sccHeadList, *sccTailList, *sccList;
02533   array_t       *rowScc, *colScc, *sccArray;
02534   long          initialTime, finalTime;
02535   int           *newRowOrder, *newColOrder;
02536   int           nCurRows, nCurCols;
02537 
02538   if (!option->mlpDecomposeScc) {
02539     sccList = ALLOC(SccList_t, 1);
02540     sccList->nFuncs = nActiveRows;
02541     sccList->nVars = nActiveCols;
02542     sccList->startFunc = 0;
02543     sccList->lastFunc = nActiveRows - 1;
02544     sccList->startVar = 0;
02545     sccList->lastVar = nActiveCols - 1;
02546     sccList->next = NIL(SccList_t);
02547     return(sccList);
02548   }
02549 
02550   if (option->mlpVerbosity >= 2)
02551     initialTime = util_cpu_time();
02552   else
02553     initialTime = 0;
02554 
02555   sccHeadList = NIL(SccList_t);
02556   sccTailList = NIL(SccList_t);
02557 
02558   rowFlag = ALLOC(char, nRows);
02559   memset(rowFlag, 0, sizeof(char) * nRows);
02560   nVars = bdd_num_vars(mddManager);
02561   colFlag = ALLOC(char, nVars);
02562   memset(colFlag, 0, sizeof(char) * nVars);
02563   stack = ALLOC(int, nActiveRows);
02564   stackFlag = ALLOC(char, nRows);
02565   memset(stackFlag, 0, sizeof(char) * nRows);
02566 
02567   startRow = 0;
02568   startCol = 0;
02569   nGroups = 0;
02570   nChosen = 0;
02571   while (nChosen < nActiveRows) {
02572     rowScc = array_alloc(int, 0);
02573     colScc = array_alloc(int, 0);
02574 
02575     size = 0;
02576     for (i = startRow; i < nActiveRows; i++) {
02577       row = rowOrder[i];
02578       if (rowFlag[row] == 0) {
02579         stack[0] = row;
02580         size = 1;
02581         stackFlag[row] = 1;
02582         break;
02583       }
02584     }
02585 
02586     while (size) {
02587       if (size + array_n(rowScc) == nRows) {
02588         FREE(stack);
02589         FREE(stackFlag);
02590         FREE(rowFlag);
02591         FREE(colFlag);
02592         array_free(rowScc);
02593         array_free(colScc);
02594 
02595         sccList = ALLOC(SccList_t, 1);
02596         sccList->nFuncs = nActiveRows;
02597         sccList->nVars = nActiveCols;
02598         sccList->startFunc = 0;
02599         sccList->lastFunc = nActiveRows - 1;
02600         sccList->startVar = 0;
02601         sccList->lastVar = nActiveCols - 1;
02602         sccList->next = NIL(SccList_t);
02603         return(sccList);
02604       }
02605 
02606       size--;
02607       row = stack[size];
02608       x = rowInfo[row].pos;
02609       rowFlag[row] = nGroups + 1;
02610       array_insert_last(int, rowScc, x);
02611       nChosen++;
02612       s1 = colInfo[rowInfo[row].gMin].pos;
02613       t1 = colInfo[rowInfo[row].gMax].pos;
02614       for (y = s1; y <= t1; y++) {
02615         col = colOrder[y];
02616         if (colInfo[col].gNum == nRows) {
02617           FREE(stack);
02618           FREE(stackFlag);
02619           FREE(rowFlag);
02620           FREE(colFlag);
02621           array_free(rowScc);
02622           array_free(colScc);
02623 
02624           sccList = ALLOC(SccList_t, 1);
02625           sccList->nFuncs = nActiveRows;
02626           sccList->nVars = nActiveCols;
02627           sccList->startFunc = 0;
02628           sccList->lastFunc = nActiveRows - 1;
02629           sccList->startVar = 0;
02630           sccList->lastVar = nActiveCols - 1;
02631           sccList->next = NIL(SccList_t);
02632           return(sccList);
02633         }
02634         if (!xy[row][col] || colFlag[col])
02635           continue;
02636         colFlag[col] = nGroups + 1;
02637         array_insert_last(int, colScc, y);
02638         s2 = rowInfo[colInfo[col].gMin].pos;
02639         t2 = rowInfo[colInfo[col].gMax].pos;
02640         for (i = s2; i <= t2; i++) {
02641           otherRow = rowOrder[i];
02642           if (rowFlag[otherRow] || stackFlag[otherRow])
02643             continue;
02644           if (xy[otherRow][col]) {
02645             stack[size] = otherRow;
02646             size++;
02647             stackFlag[otherRow] = 1;
02648           }
02649         }
02650       }
02651     }
02652 
02653     nGroups++;
02654     if (nGroups == 1 && nChosen == nActiveRows) {
02655       sccList = ALLOC(SccList_t, 1);
02656       sccList->nFuncs = nActiveRows;
02657       sccList->nVars = nActiveCols;
02658       sccList->startFunc = 0;
02659       sccList->lastFunc = nActiveRows - 1;
02660       sccList->startVar = 0;
02661       sccList->lastVar = nActiveCols - 1;
02662       sccList->next = NIL(SccList_t);
02663 
02664       sccHeadList = sccList;
02665 
02666       array_free(rowScc);
02667       array_free(colScc);
02668       break;
02669     }
02670 
02671     /* Move the rows and columns that belong to the current group to top-left */
02672     array_sort(rowScc, SccSortRc);
02673     array_sort(colScc, SccSortRc);
02674     for (i = 0; i < array_n(rowScc); i++) {
02675       x = array_fetch(int, rowScc, i);
02676       if (x == startRow + i)
02677         continue;
02678       row = rowOrder[x];
02679       for (j = x; j > startRow + i; j--) {
02680         rowOrder[j] = rowOrder[j - 1];
02681         rowInfo[rowOrder[j]].pos = j;
02682       }
02683       rowOrder[startRow + i] = row;
02684       rowInfo[row].pos = startRow + i;
02685     }
02686     for (i = 0; i < array_n(colScc); i++) {
02687       y = array_fetch(int, colScc, i);
02688       if (y == startCol + i)
02689         continue;
02690       col = colOrder[y];
02691       for (j = y; j > startCol + i; j--) {
02692         colOrder[j] = colOrder[j - 1];
02693         colInfo[colOrder[j]].pos = j;
02694       }
02695       colOrder[startCol + i] = col;
02696       colInfo[col].pos = startCol + i;
02697     }
02698 
02699     sccList = ALLOC(SccList_t, 1);
02700     sccList->nFuncs = array_n(rowScc);
02701     sccList->nVars = array_n(colScc);
02702     sccList->startFunc = startRow;
02703     sccList->lastFunc = startRow + sccList->nFuncs - 1;
02704     sccList->startVar = startCol;
02705     sccList->lastVar = startCol + sccList->nVars - 1;
02706     sccList->next = NIL(SccList_t);
02707     startRow += sccList->nFuncs;
02708     startCol += sccList->nVars;
02709 
02710     if (sccTailList)
02711       sccTailList->next = sccList;
02712     else
02713       sccHeadList = sccList;
02714     sccTailList = sccList;
02715 
02716     array_free(rowScc);
02717     array_free(colScc);
02718 
02719     if (option->mlpDebug) {
02720       CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
02721                   rowInfo, colInfo, rowOrder, colOrder,
02722                   0, nActiveRows - 1, 0, nActiveCols - 1, 1);
02723     }
02724   }
02725 
02726   FREE(stack);
02727   FREE(stackFlag);
02728   FREE(rowFlag);
02729   FREE(colFlag);
02730 
02731   if (option->mlpSortScc && clusteredFlag == 0) {
02732     sccArray = array_alloc(SccList_t *, 0);
02733     sccList = sccHeadList;
02734     while (sccList) {
02735       array_insert_last(SccList_t *, sccArray, sccList);
02736       sccList = sccList->next;
02737     }
02738 
02739     if (option->mlpSortSccMode == 0) {
02740       if (option->mlpSortScc == 1)
02741         array_sort(sccArray, SccSortListIncreasingWithArea);
02742       else
02743         array_sort(sccArray, SccSortListDecreasingWithArea);
02744     } else if (option->mlpSortSccMode == 1) {
02745       if (option->mlpSortScc == 1)
02746         array_sort(sccArray, SccSortListIncreasingWithVars);
02747       else
02748         array_sort(sccArray, SccSortListDecreasingWithVars);
02749     } else {
02750       if (option->mlpSortScc == 1)
02751         array_sort(sccArray, SccSortListIncreasingWithRatio);
02752       else
02753         array_sort(sccArray, SccSortListDecreasingWithRatio);
02754     }
02755 
02756     newRowOrder = ALLOC(int, nActiveRows);
02757     newColOrder = ALLOC(int, nActiveCols);
02758 
02759     nCurRows = 0;
02760     nCurCols = 0;
02761     sccHeadList = NIL(SccList_t);
02762     for (i = 0; i < array_n(sccArray); i++) {
02763       sccList = array_fetch(SccList_t *, sccArray, i);
02764       if (sccHeadList)
02765         sccTailList->next = sccList;
02766       else
02767         sccHeadList = sccList;
02768       sccTailList = sccList;
02769       sccList->next = NIL(SccList_t);
02770 
02771       for (j = sccList->startFunc; j <= sccList->lastFunc; j++) {
02772         row = rowOrder[j];
02773         newRowOrder[nCurRows + j - sccList->startFunc] = rowOrder[j];
02774         rowInfo[row].pos = nCurRows + j - sccList->startFunc;
02775       }
02776       sccList->startFunc = nCurRows;
02777       sccList->lastFunc = nCurRows + sccList->nFuncs - 1;
02778       nCurRows += sccList->nFuncs;
02779 
02780       for (j = sccList->startVar; j <= sccList->lastVar; j++) {
02781         col = colOrder[j];
02782         newColOrder[nCurCols + j - sccList->startVar] = colOrder[j];
02783         colInfo[col].pos = nCurCols + j - sccList->startVar;
02784       }
02785       sccList->startVar = nCurCols;
02786       sccList->lastVar = nCurCols + sccList->nVars - 1;
02787       nCurCols += sccList->nVars;
02788     }
02789 
02790     memcpy(rowOrder, newRowOrder, sizeof(int) * nActiveRows);
02791     memcpy(colOrder, newColOrder, sizeof(int) * nActiveCols);
02792 
02793     if (option->mlpDebug) {
02794       CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
02795                   rowInfo, colInfo, rowOrder, colOrder,
02796                   0, nActiveRows - 1, 0, nActiveCols - 1, 1);
02797     }
02798 
02799     FREE(newRowOrder);
02800     FREE(newColOrder);
02801     array_free(sccArray);
02802   }
02803 
02804   if (option->mlpVerbosity >= 2) {
02805     finalTime = util_cpu_time();
02806     fprintf(vis_stdout, "time for scc decomposition = %10g (#scc=%d)\n",
02807             (double)(finalTime - initialTime) / 1000.0, nGroups);
02808   }
02809 
02810   return(sccHeadList);
02811 }
02812 
02813 
02823 static int
02824 SccSortListIncreasingWithVars(const void *p1, const void *p2)
02825 {
02826   SccList_t **scc1 = (SccList_t **) p1;
02827   SccList_t **scc2 = (SccList_t **) p2;
02828   if ((*scc1)->nVars > (*scc2)->nVars)
02829     return(1);
02830   else if ((*scc1)->nVars < (*scc2)->nVars)
02831     return(-1);
02832   else
02833     return(0);
02834 }
02835 
02836 
02846 static int
02847 SccSortListDecreasingWithVars(const void *p1, const void *p2)
02848 {
02849   SccList_t **scc1 = (SccList_t **) p1;
02850   SccList_t **scc2 = (SccList_t **) p2;
02851   if ((*scc1)->nVars < (*scc2)->nVars)
02852     return(1);
02853   else if ((*scc1)->nVars > (*scc2)->nVars)
02854     return(-1);
02855   else
02856     return(0);
02857 }
02858 
02859 
02869 static int
02870 SccSortListIncreasingWithArea(const void *p1, const void *p2)
02871 {
02872   SccList_t **scc1 = (SccList_t **) p1;
02873   SccList_t **scc2 = (SccList_t **) p2;
02874   int   area1, area2;
02875 
02876   area1 = (*scc1)->nFuncs * (*scc1)->nVars;
02877   area2 = (*scc2)->nFuncs * (*scc2)->nVars;
02878   if (area1 > area2)
02879     return(1);
02880   else if (area1 < area2)
02881     return(-1);
02882   else
02883     return(0);
02884 }
02885 
02886 
02896 static int
02897 SccSortListDecreasingWithArea(const void *p1, const void *p2)
02898 {
02899   SccList_t **scc1 = (SccList_t **) p1;
02900   SccList_t **scc2 = (SccList_t **) p2;
02901   int   area1, area2;
02902 
02903   area1 = (*scc1)->nFuncs * (*scc1)->nVars;
02904   area2 = (*scc2)->nFuncs * (*scc2)->nVars;
02905   if (area1 < area2)
02906     return(1);
02907   else if (area1 > area2)
02908     return(-1);
02909   else
02910     return(0);
02911 }
02912 
02913 
02923 static int
02924 SccSortListIncreasingWithRatio(const void *p1, const void *p2)
02925 {
02926   SccList_t **scc1 = (SccList_t **) p1;
02927   SccList_t **scc2 = (SccList_t **) p2;
02928   float ratio1, ratio2;
02929 
02930   ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
02931   ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
02932   if (ratio1 > ratio2)
02933     return(1);
02934   else if (ratio1 < ratio2)
02935     return(-1);
02936   else
02937     return(0);
02938 }
02939 
02940 
02950 static int
02951 SccSortListDecreasingWithRatio(const void *p1, const void *p2)
02952 {
02953   SccList_t **scc1 = (SccList_t **) p1;
02954   SccList_t **scc2 = (SccList_t **) p2;
02955   float ratio1, ratio2;
02956 
02957   ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
02958   ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
02959   if (ratio1 < ratio2)
02960     return(1);
02961   else if (ratio1 > ratio2)
02962     return(-1);
02963   else
02964     return(0);
02965 }
02966 
02967 
02977 static int
02978 SccSortRc(const void * p1, const void * p2)
02979 {
02980   int *n1 = (int *) p1;
02981   int *n2 = (int *) p2;
02982   if (*n1 > *n2)
02983     return(1);
02984   else if (*n1 < *n2)
02985     return(-1);
02986   else
02987     return(0);
02988 }
02989 
02990 
03000 static void
03001 FreeSccList(SccList_t *sccHeadList)
03002 {
03003   SccList_t     *sccList, *sccNextList;
03004 
03005   sccList = sccHeadList;
03006   while (sccList) {
03007     sccNextList = sccList->next;
03008     FREE(sccList);
03009     sccList = sccNextList;
03010   }
03011 }
03012 
03013 
03023 static int
03024 NumOfSccs(SccList_t *sccHeadList)
03025 {
03026   SccList_t     *sccList;
03027   int           num = 0;
03028 
03029   sccList = sccHeadList;
03030   while (sccList) {
03031     num++;
03032     sccList = sccList->next;
03033   }
03034   return(num);
03035 }
03036 
03037 
03048 static void
03049 BlockLowerTriangle(char **xy, int nRows, int nCols,
03050                    int nActiveRows, int nActiveCols,
03051                    SccList_t *sccList, int *rowOrder, int *colOrder,
03052                    RcInfo_t *rowInfo, RcInfo_t *colInfo,
03053                    ImgTrmOption_t *option)
03054 {
03055   long          initialTime, finalTime;
03056   int           startFunc, lastFunc, startVar, lastVar;
03057   int           nLeftRows, nLeftCols;
03058   int           saveStartFunc, saveLastFunc;
03059   int           saveStartVar, saveLastVar;
03060 
03061   if (sccList) {
03062     if (sccList->nFuncs == 1 || sccList->nVars == 1)
03063       return;
03064     startFunc = sccList->startFunc;
03065     lastFunc = sccList->lastFunc;
03066     startVar = sccList->startVar;
03067     lastVar = sccList->lastVar;
03068   } else {
03069     startFunc = 0;
03070     lastFunc = nActiveRows - 1;
03071     startVar = 0;
03072     lastVar = nActiveCols - 1;
03073   }
03074 
03075   if (option->mlpVerbosity >= 2) {
03076     saveStartFunc = startFunc;
03077     saveLastFunc = lastFunc;
03078     saveStartVar = startVar;
03079     saveLastVar = lastVar;
03080   } else {
03081     /* To remove compiler warnings */
03082     saveStartFunc = 0;
03083     saveLastFunc = 0;
03084     saveStartVar = 0;
03085     saveLastVar = 0;
03086   }
03087 
03088   if (option->mlpDebug) {
03089     CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
03090                 rowOrder, colOrder, startFunc, lastFunc, startVar, lastVar, 1);
03091   }
03092 
03093   if (option->mlpCsFirst) {
03094     /*
03095      * Find singleton columns and move each column to the right of the active
03096      * window and move its row to the bottom of the active window.
03097      */
03098     if (option->mlpSkipCs == 0) {
03099       if (option->mlpVerbosity >= 2)
03100         initialTime = util_cpu_time();
03101       else /* to remove uninitialized variables warning */
03102         initialTime = 0;
03103       FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
03104                                &startFunc, &lastFunc, &startVar, &lastVar,
03105                                rowInfo, colInfo, rowOrder, colOrder, option);
03106       if (option->mlpVerbosity >= 2) {
03107         finalTime = util_cpu_time();
03108         fprintf(vis_stdout,
03109                 "time for col singleton = %10g (#row=%d, #col=%d)\n",
03110                 (double)(finalTime - initialTime) / 1000.0,
03111                 saveLastFunc - lastFunc, saveLastVar - lastVar);
03112       }
03113     }
03114 
03115     /*
03116      * Find singleton rows and move each row to the top of the active window
03117      * and move its column to the left of the active window.
03118      */
03119     if (option->mlpSkipRs == 0) {
03120       if (option->mlpVerbosity >= 2)
03121         initialTime = util_cpu_time();
03122       else /* to remove uninitialized variables warning */
03123         initialTime = 0;
03124       FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
03125                                &startFunc, &lastFunc, &startVar, &lastVar,
03126                                rowInfo, colInfo, rowOrder, colOrder, option);
03127       if (option->mlpVerbosity >= 2) {
03128         finalTime = util_cpu_time();
03129         fprintf(vis_stdout,
03130                 "time for row singleton = %10g (#row=%d, #col=%d)\n",
03131                 (double)(finalTime - initialTime) / 1000.0,
03132                 startFunc - saveStartFunc, startVar - saveStartVar);
03133       }
03134     }
03135   } else {
03136     /*
03137      * Find singleton rows and move each row to the top of the active window
03138      * and move its column to the left of the active window.
03139      */
03140     if (option->mlpSkipRs == 0) {
03141       if (option->mlpVerbosity >= 2)
03142         initialTime = util_cpu_time();
03143       else /* to remove uninitialized variables warning */
03144         initialTime = 0;
03145       FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
03146                                &startFunc, &lastFunc, &startVar, &lastVar,
03147                                rowInfo, colInfo, rowOrder, colOrder, option);
03148       if (option->mlpVerbosity >= 2) {
03149         finalTime = util_cpu_time();
03150         fprintf(vis_stdout,
03151                 "time for row singleton = %10g (#row=%d, #col=%d)\n",
03152                 (double)(finalTime - initialTime) / 1000.0,
03153                 startFunc - saveStartFunc, startVar - saveStartVar);
03154       }
03155     }
03156 
03157     /*
03158      * Find singleton columns and move each column to the right of the active
03159      * window and move its row to the bottom of the active window.
03160      */
03161     if (option->mlpSkipCs == 0) {
03162       if (option->mlpVerbosity >= 2)
03163         initialTime = util_cpu_time();
03164       else /* to remove uninitialized variables warning */
03165         initialTime = 0;
03166       FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
03167                                &startFunc, &lastFunc, &startVar, &lastVar,
03168                                rowInfo, colInfo, rowOrder, colOrder, option);
03169       if (option->mlpVerbosity >= 2) {
03170         finalTime = util_cpu_time();
03171         fprintf(vis_stdout,
03172                 "time for col singleton = %10g (#row=%d, #col=%d)\n",
03173                 (double)(finalTime - initialTime) / 1000.0,
03174                 saveLastFunc - lastFunc, saveLastVar - lastVar);
03175       }
03176     }
03177   }
03178 
03179   if (option->mlpVerbosity >= 2) {
03180     initialTime = util_cpu_time();
03181     nLeftRows = lastFunc - startFunc + 1;
03182     nLeftCols = lastVar - startVar + 1;
03183   } else {
03184     /* To remove compiler warnings */
03185     initialTime = 0;
03186     nLeftRows = 0;
03187     nLeftCols = 0;
03188   }
03189 
03190   if (option->mlpRowBased) {
03191     MoveBestRows(xy, sccList, nActiveRows, nActiveCols, rowOrder, colOrder,
03192                  rowInfo, colInfo,
03193                  startFunc, lastFunc, startVar, lastVar, option);
03194   } else {
03195     MoveBestCols(xy, sccList, nRows, nCols, nActiveRows, nActiveCols,
03196                  rowOrder, colOrder, rowInfo, colInfo,
03197                  startFunc, lastFunc, startVar, lastVar, option);
03198   }
03199 
03200   if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03201     PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
03202                 rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
03203   }
03204 
03205   if (option->mlpVerbosity >= 2) {
03206     finalTime = util_cpu_time();
03207     if (option->mlpRowBased) {
03208       fprintf(vis_stdout, "time for best row = %10g (#row=%d, #col=%d)\n",
03209                 (double)(finalTime - initialTime) / 1000.0,
03210                 nLeftRows - lastFunc + startFunc - 1,
03211                 nLeftCols - lastVar + startVar - 1);
03212     } else {
03213       fprintf(vis_stdout, "time for best col = %10g (#row=%d, #col=%d)\n",
03214                 (double)(finalTime - initialTime) / 1000.0,
03215                 nLeftRows - lastFunc + startFunc - 1,
03216                 nLeftCols - lastVar + startVar - 1);
03217     }
03218   }
03219 }
03220 
03221 
03231 static void
03232 MoveBestRows(char **xy, SccList_t *sccList, int nRows, int nCols,
03233                 int *rowOrder, int *colOrder,
03234                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
03235                 int startFunc, int lastFunc, int startVar, int lastVar,
03236                 ImgTrmOption_t *option)
03237 {
03238   int           x, y, s1, t1, s2, t2;
03239   int           min, bestX;
03240   int           row, col, lastCol, moveRow, bestRow;
03241   int           regionX, overlap, nOverlaps, nMore;
03242 
03243   regionX = 0;
03244   bestX = -1;
03245   while (startFunc < lastFunc && startVar < lastVar) {
03246     min = nCols;
03247     overlap = 0;
03248     for (x = startFunc; x <= lastFunc; x++) {
03249       row = rowOrder[x];
03250       assert(rowInfo[row].lNum);
03251       if (overlap) {
03252         if (rowInfo[row].lNum < min) {
03253           s1 = colInfo[rowInfo[row].gMin].pos;
03254           if (s1 < regionX)
03255             s1 = regionX;
03256           nOverlaps = 0;
03257           for (y = s1; y < startVar; y++) {
03258             col = colOrder[y];
03259             if (xy[row][col]) {
03260               nOverlaps++;
03261               break;
03262             }
03263           }
03264 
03265           if (nOverlaps) {
03266             bestX = x;
03267             min = rowInfo[row].lNum;
03268           }
03269         }
03270       } else {
03271         s1 = colInfo[rowInfo[row].gMin].pos;
03272         if (s1 < regionX)
03273           s1 = regionX;
03274         nOverlaps = 0;
03275         for (y = s1; y < startVar; y++) {
03276           col = colOrder[y];
03277           if (xy[row][col]) {
03278             nOverlaps++;
03279             break;
03280           }
03281         }
03282 
03283         if (nOverlaps) {
03284           bestX = x;
03285           min = rowInfo[row].lNum;
03286           overlap = 1;
03287         } else {
03288           if (rowInfo[row].lNum < min) {
03289             bestX = x;
03290             min = rowInfo[row].lNum;
03291           }
03292         }
03293       }
03294     }
03295 
03296     assert(bestX != -1);
03297     if (!overlap)
03298       regionX = startFunc;
03299 
03300     row = rowOrder[bestX];
03301     while (1) {
03302       bestRow = row;
03303       s1 = colInfo[rowInfo[row].lMin].pos;
03304       t1 = colInfo[rowInfo[row].lMax].pos;
03305       min = rowInfo[row].lNum;
03306       for (x = startFunc; x <= lastFunc; x++) {
03307         moveRow = rowOrder[x];
03308         if (moveRow == row)
03309           continue;
03310         s2 = colInfo[rowInfo[moveRow].lMin].pos;
03311         t2 = colInfo[rowInfo[moveRow].lMax].pos;
03312         if (s2 < s1 || t2 > t1)
03313           continue;
03314         nMore = 0;
03315         nOverlaps = 0;
03316         for (y = s2; y <= t2; y++) {
03317           col = colOrder[y];
03318           if (xy[row][col]) {
03319             if (xy[moveRow][col])
03320               nOverlaps++;
03321           } else {
03322             if (xy[moveRow][col]) {
03323               nMore++;
03324               break;
03325             }
03326           }
03327         }
03328         if (nMore || nOverlaps == 0 || nOverlaps >= min)
03329           continue;
03330         min = nOverlaps;
03331         bestRow = moveRow;
03332       }
03333 
03334       lastCol = -1;
03335       s1 = colInfo[rowInfo[bestRow].lMin].pos;
03336       t1 = colInfo[rowInfo[bestRow].lMax].pos;
03337       for (y = s1; y <= t1; y++) {
03338         col = colOrder[y];
03339         if (xy[bestRow][col]) {
03340           if (option->mlpVerbosity >= 3) {
03341             fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (best row)\n",
03342                     nMoves, y, col, startVar);
03343             fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03344                     startFunc, lastFunc, startVar, lastVar);
03345           }
03346           MoveColToLeft(xy, y, startFunc, lastFunc, startVar, lastVar,
03347                           rowInfo, colInfo, rowOrder, colOrder,
03348                           NIL(RcListInfo_t), option->mlpMethod);
03349           startVar++;
03350           lastCol = col;
03351 
03352           if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03353             PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
03354                         startFunc, lastFunc, startVar, lastVar);
03355           }
03356           if (option->mlpDebug) {
03357             CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
03358                         rowOrder, colOrder,
03359                         startFunc, lastFunc, startVar, lastVar, 1);
03360           }
03361         }
03362       }
03363 
03364       if (lastCol != -1) {
03365         s2 = rowInfo[colInfo[lastCol].lMin].pos;
03366         t2 = rowInfo[colInfo[lastCol].lMax].pos;
03367         for (x = s2; x <= t2; x++) {
03368           moveRow = rowOrder[x];
03369           if (xy[moveRow][lastCol] && rowInfo[moveRow].lNum == 0) {
03370             if (option->mlpVerbosity >= 3) {
03371               fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (best row)\n",
03372                         nMoves, x, moveRow, startFunc);
03373               fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03374                         startFunc, lastFunc, startVar, lastVar);
03375             }
03376             MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
03377                          rowInfo, colInfo, rowOrder, colOrder,
03378                          NIL(RcListInfo_t), option->mlpMethod);
03379             startFunc++;
03380             if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03381               PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
03382                           rowInfo, colInfo,
03383                           startFunc, lastFunc, startVar, lastVar);
03384             }
03385             if (option->mlpDebug) {
03386               CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
03387                           rowOrder, colOrder,
03388                           startFunc, lastFunc, startVar, lastVar, 1);
03389             }
03390           }
03391         }
03392       }
03393 
03394       if (row == bestRow)
03395         break;
03396     }
03397   }
03398 }
03399 
03400 
03410 static void
03411 MoveBestCols(char **xy, SccList_t *sccList, int nRows, int nCols,
03412                 int nActiveRows, int nActiveCols,
03413                 int *rowOrder, int *colOrder,
03414                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
03415                 int startFunc, int lastFunc, int startVar, int lastVar,
03416                 ImgTrmOption_t *option)
03417 {
03418   int           x, y, i, s1, t1, s2, t2;
03419   char          *rowFlag, *colFlag;
03420   int           min, bestY, bestCol;
03421   int           row, col, tie, newTies, intersect = 0, maxIntersect, maxLength;
03422   int           minX, maxX;
03423   RcListInfo_t  *sortedRows, *sortedCols;
03424   RcList_t      *cur, *list;
03425 
03426   if (option->mlpSortedRows) {
03427     sortedRows = SortedListAlloc();
03428     for (x = startFunc; x <= lastFunc; x++) {
03429       row = rowOrder[x];
03430       SortedListInsert(sortedRows, row, row, rowInfo, 3);
03431     }
03432 
03433     if (option->mlpSortedCols)
03434       sortedCols = SortedListAlloc();
03435     else
03436       sortedCols = NIL(RcListInfo_t);
03437 
03438     if (option->mlpDebug)
03439       CheckSortedList(sortedRows, rowInfo, 3);
03440   } else {
03441     sortedRows = NIL(RcListInfo_t);
03442     sortedCols = NIL(RcListInfo_t);
03443   }
03444 
03445   rowFlag = ALLOC(char, nRows);
03446   if (sortedCols)
03447     memset(rowFlag, 0, sizeof(char) * nRows);
03448   colFlag = ALLOC(char, nCols);
03449   while (startFunc != lastFunc && startVar != lastVar) {
03450     min = nActiveCols;
03451     if (!sortedCols)
03452       memset(rowFlag, 0, sizeof(char) * nRows);
03453     tie = 0;
03454     minX = lastFunc;
03455     maxX = startFunc;
03456     if (sortedCols) {
03457       bestY = nActiveCols;
03458       bestCol = nActiveCols;
03459       if (sortedCols->num == 0) {
03460         if (sortedRows) {
03461           cur = sortedRows->head;
03462           while (cur) {
03463             row = cur->index;
03464             x = rowInfo[row].pos;
03465             if (rowInfo[row].lNum == 0) {
03466               cur = cur->next;
03467               continue;
03468             }
03469             if (rowInfo[row].lNum > min)
03470               break;
03471             rowFlag[row] = 1;
03472             s1 = colInfo[rowInfo[row].lMin].pos;
03473             t1 = colInfo[rowInfo[row].lMax].pos;
03474             for (y = s1; y <= t1; y++) {
03475               col = colOrder[y];
03476               if (!xy[row][col])
03477                 continue;
03478               if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
03479                 list->otherIndex++;
03480                 SortedListMove(sortedCols, colInfo, col, 4);
03481               } else
03482                 SortedListInsert(sortedCols, col, 1, colInfo, 4);
03483             }
03484             min = rowInfo[row].lNum;
03485             tie++;
03486             cur = cur->next;
03487           }
03488         }
03489       } else {
03490         if (sortedRows) {
03491           cur = sortedRows->head;
03492           while (cur) {
03493             row = cur->index;
03494             x = rowInfo[row].pos;
03495             if (rowInfo[row].lNum == 0) {
03496               cur = cur->next;
03497               continue;
03498             }
03499             if (rowInfo[row].lNum > min)
03500               break;
03501             min = rowInfo[row].lNum;
03502             tie++;
03503             cur = cur->next;
03504           }
03505         }
03506       }
03507 
03508       if (option->mlpDebug) {
03509         if (sortedRows)
03510           CheckSortedList(sortedRows, rowInfo, 3);
03511         CheckSortedList(sortedCols, colInfo, 4);
03512       }
03513 
03514       bestCol = sortedCols->head->index;
03515       bestY = colInfo[bestCol].pos;
03516       assert(bestY >= startVar && bestY <= lastVar);
03517       maxLength = colInfo[bestCol].lNum;
03518       intersect = sortedCols->head->otherIndex;
03519     } else {
03520       if (sortedRows) {
03521         if (option->mlpDebug)
03522           CheckSortedList(sortedRows, rowInfo, 3);
03523 
03524         cur = sortedRows->head;
03525         while (cur) {
03526           row = cur->index;
03527           x = rowInfo[row].pos;
03528           if (rowInfo[row].lNum == 0) {
03529             cur = cur->next;
03530             continue;
03531           }
03532           if (rowInfo[row].lNum < min) {
03533             min = rowInfo[row].lNum;
03534             tie = 1;
03535             memset(rowFlag, 0, sizeof(char) * nRows);
03536             rowFlag[x] = 1;
03537             minX = x;
03538             maxX = x;
03539           } else if (rowInfo[row].lNum == min) {
03540             tie++;
03541             rowFlag[x] = 1;
03542             if (x < minX)
03543               minX = x;
03544             if (x > maxX)
03545               maxX = x;
03546           } else
03547             break;
03548           cur = cur->next;
03549         }
03550       } else {
03551         for (x = startFunc; x <= lastFunc; x++) {
03552           row = rowOrder[x];
03553           if (rowInfo[row].lNum == 0)
03554             continue;
03555           if (rowInfo[row].lNum < min) {
03556             min = rowInfo[row].lNum;
03557             tie = 1;
03558             memset(rowFlag, 0, sizeof(char) * nRows);
03559             rowFlag[x] = 1;
03560             minX = x;
03561             maxX = x;
03562           } else if (rowInfo[row].lNum == min) {
03563             tie++;
03564             rowFlag[x] = 1;
03565             maxX = x;
03566           }
03567         }
03568       }
03569 
03570       if (tie == 0)
03571         break;
03572 
03573       maxLength = 0;
03574       maxIntersect = 0;
03575       memset(colFlag, 0, sizeof(char) * nCols);
03576       bestY = nActiveCols;
03577       bestCol = nActiveCols;
03578       for (x = minX; x <= maxX; x++) {
03579         if (!rowFlag[x])
03580           continue;
03581         row = rowOrder[x];
03582         s1 = colInfo[rowInfo[row].lMin].pos;
03583         t1 = colInfo[rowInfo[row].lMax].pos;
03584         for (y = s1; y <= t1; y++) {
03585           col = colOrder[y];
03586           if (xy[row][col]) {
03587             if (colFlag[y])
03588               continue;
03589             colFlag[y] = 1;
03590             intersect = 0;
03591             s2 = rowInfo[colInfo[col].lMin].pos;
03592             t2 = rowInfo[colInfo[col].lMax].pos;
03593             if (s2 < minX)
03594               s2 = minX;
03595             if (t2 > maxX)
03596               t2 = maxX;
03597             for (i = s2; i <= t2; i++) {
03598               if (xy[rowOrder[i]][col]) {
03599                 if (rowFlag[i])
03600                   intersect++;
03601               }
03602             }
03603             if (intersect > maxIntersect ||
03604                 (intersect == maxIntersect && colInfo[col].lNum > maxLength) ||
03605                 (intersect == maxIntersect && colInfo[col].lNum == maxLength &&
03606                   y < bestY)) {
03607               bestY = y;
03608               bestCol = colOrder[bestY];
03609               maxLength = colInfo[bestCol].lNum;
03610               maxIntersect = intersect;
03611             }
03612           }
03613         }
03614       }
03615     }
03616 
03617     if (option->mlpVerbosity >= 3) {
03618       fprintf(vis_stdout,
03619 "[%d] Moving Col %d(%d) to %d (best col, min=%d, intersect=%d, length=%d)\n",
03620              nMoves, bestY, bestCol, startVar, min, intersect, maxLength);
03621       fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03622              startFunc, lastFunc, startVar, lastVar);
03623     }
03624     MoveColToLeft(xy, bestY, startFunc, lastFunc, startVar, lastVar,
03625                   rowInfo, colInfo, rowOrder, colOrder,
03626                   NIL(RcListInfo_t), option->mlpMethod);
03627     startVar++;
03628     if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03629       PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
03630                   rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
03631     }
03632     if (option->mlpDebug) {
03633       CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
03634                   rowOrder, colOrder,
03635                   startFunc, lastFunc, startVar, lastVar, 1);
03636     }
03637 
03638     if (sortedCols)
03639       SortedListDelete(sortedCols, bestCol);
03640 
03641     if (sortedRows) {
03642       if (min == 1) {
03643         cur = sortedRows->head;
03644         while (cur) {
03645           row = cur->index;
03646           if (rowInfo[row].lNum > min)
03647             break;
03648           else if (rowInfo[row].lNum == min) {
03649             cur = cur->next;
03650             continue;
03651           }
03652           x = rowInfo[row].pos;
03653           if (option->mlpVerbosity >= 3) {
03654             fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
03655                    nMoves, x, row, startFunc);
03656             fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03657                    startFunc, lastFunc, startVar, lastVar);
03658           }
03659           MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
03660                        rowInfo, colInfo, rowOrder, colOrder,
03661                        NIL(RcListInfo_t), option->mlpMethod);
03662           startFunc++;
03663           if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03664             PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
03665                         rowInfo, colInfo,
03666                         startFunc, lastFunc, startVar, lastVar);
03667           }
03668           if (option->mlpDebug) {
03669             CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
03670                         rowInfo, colInfo, rowOrder, colOrder,
03671                         startFunc, lastFunc, startVar, lastVar, 1);
03672           }
03673           cur = cur->next;
03674           SortedListDelete(sortedRows, row);
03675         }
03676       }
03677 
03678       /* Update sortedRows */
03679       /*
03680       cur = sortedRows->head;
03681       while (cur) {
03682         row = cur->index;
03683         if (xy[row][bestCol]) {
03684           assert(rowInfo[row].lNum > 0);
03685           SortedListMove(sortedRows, rowInfo, row, 3);
03686         }
03687         cur = cur->next;
03688       }
03689       if (option->mlpDebug)
03690         CheckSortedList(sortedRows, rowInfo, 3);
03691       */
03692       s1 = rowInfo[colInfo[bestCol].lMin].pos;
03693       t1 = rowInfo[colInfo[bestCol].lMax].pos;
03694       cur = sortedRows->head;
03695       while (cur) {
03696         row = cur->index;
03697         x = rowInfo[row].pos;
03698         if (x < s1) {
03699           cur = cur->next;
03700           continue;
03701         }
03702         if (xy[row][bestCol] && rowInfo[row].lNum > 0) {
03703           SortedListMove(sortedRows, rowInfo, row, 3);
03704           if (sortedCols && min == 1) {
03705             if (rowInfo[row].lNum == 1 && rowFlag[row] == 0) {
03706               rowFlag[row] = 1;
03707               s2 = colInfo[rowInfo[row].lMin].pos;
03708               t2 = colInfo[rowInfo[row].lMax].pos;
03709               for (y = s2; y <= t2; y++) {
03710                 col = colOrder[y];
03711                 if (!xy[row][col])
03712                   continue;
03713                 if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
03714                   list->otherIndex++;
03715                   SortedListMove(sortedCols, colInfo, col, 4);
03716                 } else
03717                   SortedListInsert(sortedCols, col, 1, colInfo, 4);
03718               }
03719             }
03720           }
03721         }
03722         cur = cur->next;
03723       }
03724 
03725       newTies = 0;
03726       if (sortedCols && min > 1) {
03727         min = nActiveCols;
03728         cur = sortedRows->head;
03729         while (cur) {
03730           row = cur->index;
03731           x = rowInfo[row].pos;
03732           if (rowInfo[row].lNum == 0) {
03733             cur = cur->next;
03734             continue;
03735           }
03736           if (rowInfo[row].lNum > min)
03737             break;
03738           min = rowInfo[row].lNum;
03739           newTies++;
03740           cur = cur->next;
03741         }
03742 
03743         if (newTies != tie) {
03744           SortedListFree(sortedCols);
03745           sortedCols = SortedListAlloc();
03746 
03747           cur = sortedRows->head;
03748           while (cur) {
03749             row = cur->index;
03750             x = rowInfo[row].pos;
03751             if (rowInfo[row].lNum == 0) {
03752               cur = cur->next;
03753               continue;
03754             }
03755             if (rowInfo[row].lNum > min)
03756               break;
03757             rowFlag[row] = 1;
03758             s1 = colInfo[rowInfo[row].lMin].pos;
03759             t1 = colInfo[rowInfo[row].lMax].pos;
03760             for (y = s1; y <= t1; y++) {
03761               col = colOrder[y];
03762               if (!xy[row][col])
03763                 continue;
03764               if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
03765                 list->otherIndex++;
03766                 SortedListMove(sortedCols, colInfo, col, 4);
03767               } else
03768                 SortedListInsert(sortedCols, col, 1, colInfo, 4);
03769             }
03770             cur = cur->next;
03771           }
03772         }
03773       }
03774     } else {
03775       if (min == 1) {
03776         s1 = rowInfo[colInfo[bestCol].lMin].pos;
03777         t1 = rowInfo[colInfo[bestCol].lMax].pos;
03778         for (x = s1; x <= t1; x++) {
03779           row = rowOrder[x];
03780           if (xy[row][bestCol] && rowInfo[row].lNum == 0) {
03781             if (option->mlpVerbosity >= 3) {
03782               fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
03783                      nMoves, x, row, startFunc);
03784               fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03785                      startFunc, lastFunc, startVar, lastVar);
03786             }
03787             MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
03788                          rowInfo, colInfo, rowOrder, colOrder,
03789                          NIL(RcListInfo_t), option->mlpMethod);
03790             startFunc++;
03791             if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03792               PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
03793                           rowInfo, colInfo,
03794                           startFunc, lastFunc, startVar, lastVar);
03795             }
03796             if (option->mlpDebug) {
03797               CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
03798                           rowInfo, colInfo, rowOrder, colOrder,
03799                           startFunc, lastFunc, startVar, lastVar, 1);
03800             }
03801           }
03802         }
03803       }
03804     }
03805   }
03806 
03807   if (sortedRows) {
03808     cur = sortedRows->head;
03809     while (cur) {
03810       row = cur->index;
03811       x = rowInfo[row].pos;
03812       if (option->mlpVerbosity >= 3) {
03813         fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (bandwidth)\n",
03814                nMoves, x, row, startFunc);
03815         fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
03816                startFunc, lastFunc, startVar, lastVar);
03817       }
03818       MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
03819                    rowInfo, colInfo, rowOrder, colOrder,
03820                    NIL(RcListInfo_t), option->mlpMethod);
03821       startFunc++;
03822       if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03823         PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
03824                     rowInfo, colInfo,
03825                     startFunc, lastFunc, startVar, lastVar);
03826       }
03827       if (option->mlpDebug) {
03828         CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
03829                     rowOrder, colOrder,
03830                     startFunc, lastFunc, startVar, lastVar, 1);
03831       }
03832       cur = cur->next;
03833       SortedListDelete(sortedRows, row);
03834     }
03835     SortedListFree(sortedRows);
03836   }
03837 
03838   if (sortedCols) {
03839     cur = sortedCols->head;
03840     while (cur) {
03841       col = cur->index;
03842       cur = cur->next;
03843       SortedListDelete(sortedCols, col);
03844     }
03845     SortedListFree(sortedCols);
03846   }
03847 
03848   FREE(rowFlag);
03849   FREE(colFlag);
03850 }
03851 
03852 
03863 static void
03864 MlpPostProcess(char **xy, SccList_t *sccList, int nVars, int nRows, int nCols,
03865                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
03866                 int *rowOrder, int *colOrder,
03867                 Img_DirectionType direction, ImgTrmOption_t *option)
03868 {
03869   int           x, y, i, j, r, c, row, col, otherRow, otherCol, tmpRow, tmpCol;
03870   int           nqv1, nqv2, niv1, niv2, benefit1, benefit2;
03871   int           s1, t1, s2, t2, s3, t3, s4, t4;
03872   long          initialTime, finalTime;
03873   int           nSwaps;
03874   float         lambda1, lambda2, lambda3;
03875   int           startFunc, lastFunc;
03876 
03877   if (sccList) {
03878     startFunc = sccList->startFunc;
03879     lastFunc = sccList->lastFunc;
03880   } else {
03881     startFunc = 0;
03882     lastFunc = nRows - 1;
03883   }
03884 
03885   if (option->mlpVerbosity)
03886     initialTime = util_cpu_time();
03887   else
03888     initialTime = 0;
03889 
03890   nSwaps = 0;
03891   for (x = lastFunc - 1; x >= startFunc; x--) {
03892     row = rowOrder[x];
03893     if (rowInfo[row].data.row.nsVarBddArray)
03894       niv1 = array_n(rowInfo[row].data.row.nsVarBddArray);
03895     else
03896       niv1 = 0;
03897 
03898     col = rowInfo[row].gMin;
03899     if (rowInfo[row].gNum == 1 &&
03900         colInfo[col].gNum > 1 && colInfo[col].gMin == x) {
03901       t1 = rowInfo[colInfo[col].gMax].pos;
03902       for (i = x + 1; i <= t1; i++) {
03903         otherRow = rowOrder[i];
03904         if (xy[otherRow][col]) {
03905           if (x < i - 1) {
03906             for (j = x; j < i - 1; j++) {
03907               rowOrder[j] = rowOrder[j + 1];
03908               rowInfo[rowOrder[j]].pos = j;
03909             }
03910             rowOrder[i - 1] = row;
03911             rowInfo[row].pos = i - 1;
03912 
03913             if (rowInfo[otherRow].gNum == 1)
03914               break;
03915 
03916             s2 = colInfo[rowInfo[otherRow].gMin].pos;
03917             t2 = colInfo[rowInfo[otherRow].gMax].pos;
03918             for (j = t2; j >= s2; j--) {
03919               otherCol = colOrder[j];
03920               if (colInfo[otherCol].gMin == otherRow)
03921                 t2 = j - 1;
03922               else
03923                 break;
03924             }
03925 
03926             s3 = rowInfo[colInfo[col].gMin].pos;
03927             t3 = rowInfo[colInfo[col].gMax].pos;
03928             for (r = s3; r <= t3; r++) {
03929               tmpRow = rowOrder[r];
03930               if (col == rowInfo[tmpRow].gMin) {
03931                 s4 = colInfo[rowInfo[tmpRow].gMin].pos;
03932                 t4 = colInfo[rowInfo[tmpRow].gMax].pos;
03933                 if (t4 > t2)
03934                   t4 = t2;
03935                 for (c = s4 + 1; c <= t4; c++) {
03936                   tmpCol = colOrder[c];
03937                   if (xy[tmpRow][tmpCol]) {
03938                     rowInfo[tmpRow].gMin = tmpCol;
03939                     rowInfo[tmpRow].lMin = tmpCol;
03940                     break;
03941                   }
03942                 }
03943               }
03944 
03945               if (xy[tmpRow][col] && t2 >= colInfo[rowInfo[tmpRow].gMax].pos) {
03946                 rowInfo[tmpRow].gMax = col;
03947                 rowInfo[tmpRow].lMax = col;
03948               }
03949             }
03950 
03951             y = colInfo[col].pos;
03952             if (y < t2) {
03953               for (j = y; j < t2; j++) {
03954                 colOrder[j] = colOrder[j + 1];
03955                 colInfo[colOrder[j]].pos = j;
03956               }
03957               colOrder[t2] = col;
03958               colInfo[col].pos = t2;
03959             }
03960 
03961             if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
03962               PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
03963                           rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
03964             }
03965             if (option->mlpDebug) {
03966               CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
03967                           rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
03968             }
03969 
03970             nSwaps++;
03971           }
03972           break;
03973         }
03974       }
03975       continue;
03976     }
03977 
03978     for (i = x + 1; i <= lastFunc; i++) {
03979       otherRow = rowOrder[i];
03980       if (rowInfo[otherRow].data.row.nsVarBddArray)
03981         niv2 = array_n(rowInfo[otherRow].data.row.nsVarBddArray);
03982       else
03983         niv2 = 0;
03984 
03985       nqv1 = 0;
03986       s1 = colInfo[rowInfo[row].gMin].pos;
03987       t1 = colInfo[rowInfo[row].gMax].pos;
03988       for (y = t1; y >= s1; y--) {
03989         col = colOrder[y];
03990         if (colInfo[col].gMin == row) {
03991           if (!xy[otherRow][col])
03992             nqv1++;
03993         } else
03994           break;
03995       }
03996       benefit1 = nqv1 - niv1;
03997 
03998       nqv2 = 0;
03999       s2 = colInfo[rowInfo[otherRow].gMin].pos;
04000       t2 = colInfo[rowInfo[otherRow].gMax].pos;
04001       for (y = t2; y >= s2; y--) {
04002         col = colOrder[y];
04003         if (colInfo[col].gMin == otherRow)
04004           nqv2++;
04005         else
04006           break;
04007       }
04008       benefit2 = nqv2 - niv2;
04009 
04010       if (benefit1 > benefit2 ||
04011           (benefit1 == benefit2 &&
04012            (rowInfo[row].gNum > rowInfo[otherRow].gNum ||
04013             (rowInfo[row].gNum == rowInfo[otherRow].gNum &&
04014              bdd_size(rowInfo[row].data.row.func) <
04015              bdd_size(rowInfo[otherRow].data.row.func))))) {
04016         nqv1 = 0;
04017         for (y = t1; y >= s1; y--) {
04018           if (t1 > t2)
04019             break;
04020           col = colOrder[y];
04021           if (colInfo[col].gMin == row) {
04022             if (!xy[otherRow][col]) {
04023               s3 = rowInfo[colInfo[col].gMin].pos;
04024               t3 = rowInfo[colInfo[col].gMax].pos;
04025               for (r = s3; r <= t3; r++) {
04026                 tmpRow = rowOrder[r];
04027                 if (col == rowInfo[tmpRow].gMin) {
04028                   s4 = colInfo[rowInfo[tmpRow].gMin].pos;
04029                   t4 = colInfo[rowInfo[tmpRow].gMax].pos;
04030                   if (t4 > t2 - nqv1)
04031                     t4 = t2 - nqv1;
04032                   for (c = s4 + 1; c <= t4; c++) {
04033                     tmpCol = colOrder[c];
04034                     if (xy[tmpRow][tmpCol] && colInfo[tmpCol].gMin != row) {
04035                       rowInfo[tmpRow].gMin = tmpCol;
04036                       rowInfo[tmpRow].lMin = tmpCol;
04037                       break;
04038                     }
04039                   }
04040                 }
04041 
04042                 if (nqv1 == 0 && xy[tmpRow][col] &&
04043                     t2 - nqv1 >= colInfo[rowInfo[tmpRow].gMax].pos) {
04044                   rowInfo[tmpRow].gMax = col;
04045                   rowInfo[tmpRow].lMax = col;
04046                 }
04047               }
04048 
04049               for (j = y; j < t2 - nqv1; j++) {
04050                 colOrder[j] = colOrder[j + 1];
04051                 colInfo[colOrder[j]].pos = j;
04052               }
04053               colOrder[t2 - nqv1] = col;
04054               colInfo[col].pos = t2 - nqv1;
04055               nqv1++;
04056             } else {
04057               colInfo[col].gMin = otherRow;
04058               colInfo[col].lMin = otherRow;
04059               if (colInfo[col].gMax == otherRow) {
04060                 colInfo[col].gMax = row;
04061                 colInfo[col].lMax = row;
04062               }
04063             }
04064           } else {
04065             if (colInfo[col].gMax == otherRow && xy[row][col]) {
04066               colInfo[col].gMax = row;
04067               colInfo[col].lMax = row;
04068             }
04069           }
04070         }
04071 
04072         rowOrder[i - 1] = otherRow;
04073         rowInfo[otherRow].pos = i - 1;
04074         rowOrder[i] = row;
04075         rowInfo[row].pos = i;
04076         nSwaps++;
04077 
04078         if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
04079           PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
04080                         rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
04081         }
04082         if (option->mlpDebug) {
04083           CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
04084                         rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
04085         }
04086       } else
04087         break;
04088     }
04089   }
04090 
04091   if (option->mlpVerbosity) {
04092     if (option->mlpVerbosity >= 2) {
04093       lambda1 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
04094                                  rowOrder, colOrder, direction, 0, 0, option);
04095       lambda2 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
04096                                  rowOrder, colOrder, direction, 1, 0, option);
04097       lambda3 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
04098                                  rowOrder, colOrder, direction, 2, 0, option);
04099       fprintf(vis_stdout, "Optimized Lambda = %f (%f, %f)\n",
04100               lambda1, lambda2, lambda3);
04101     }
04102     finalTime = util_cpu_time();
04103     fprintf(vis_stdout, "time for postprocessing = %10g (#swap=%d)\n",
04104            (double)(finalTime - initialTime) / 1000.0, nSwaps);
04105   }
04106 }
04107 
04108 
04118 static float
04119 ComputeLambdaMlp(char **xy, int nVars, int nRows, int nCols,
04120                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
04121                 int *rowOrder, int *colOrder,
04122                 Img_DirectionType direction,
04123                 int mode, int asIs, ImgTrmOption_t *option)
04124 {
04125   int           lifetime, area;
04126   int           highest, lowest;
04127   int           x, y, row, col;
04128   int           nIntroducedVars, nYVars;
04129   float         lambda;
04130 
04131   lifetime = 0;
04132 
04133   if (direction == Img_Forward_c) {
04134     for (y = 0; y < nCols; y++) {
04135       col = colOrder[y];
04136       lowest = rowInfo[colInfo[col].gMin].pos;
04137       if (mode == 1) { /* active lifetime (alpha) */
04138         highest = rowInfo[colInfo[col].gMax].pos;
04139         lifetime += highest - lowest + 1;
04140       } else { /* total lifetime (lambda) */
04141         lifetime += nRows - lowest;
04142       }
04143     }
04144   } else {
04145     for (y = 0; y < nCols; y++) {
04146       col = colOrder[y];
04147       lowest = rowInfo[colInfo[col].gMin].pos;
04148       if (mode == 1) { /* active lifetime (alpha) */
04149         highest = rowInfo[colInfo[col].gMax].pos;
04150         lifetime += highest - lowest + 1;
04151       } else { /* total lifetime (lambda) */
04152         if (colInfo[col].data.col.type == 2) /* primary input variables */
04153           lifetime += lowest + 1;
04154         else { /* present state variables */
04155           if (mode == 2)
04156             lifetime += nRows - lowest;
04157         }
04158       }
04159     }
04160   }
04161 
04162   /* total lifetime (lambda) with introducedVars */
04163   nIntroducedVars = 0;;
04164   if (mode == 2 || (mode == 0 && direction == Img_Backward_c)) {
04165     if (asIs) { /* contains next state variables */
04166       for (x = 0; x < nRows; x++) {
04167         row = rowOrder[x];
04168         nYVars = array_n(rowInfo[row].data.row.nsVarBddArray);
04169         nIntroducedVars += nYVars;
04170         lifetime += (x + 1) * nYVars;
04171       }
04172     } else { /* does not contain next state variables */
04173       nIntroducedVars = nRows;
04174       lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
04175     }
04176   }
04177 
04178   if (option->mlpLambdaMode == 0)
04179     area = nRows * (nCols + nIntroducedVars);
04180   else
04181     area = nRows * (nVars + nIntroducedVars);
04182   lambda = (float)lifetime / (float)area;
04183   return(lambda);
04184 }
04185 
04186 
04196 static void
04197 FindAndMoveSingletonRows(char **xy, SccList_t *sccList, int nRows, int nCols,
04198         int *startFunc, int *lastFunc, int *startVar, int *lastVar,
04199         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04200         ImgTrmOption_t *option)
04201 {
04202   int           x, row, col, add, found;
04203   RcListInfo_t  *candList;
04204 
04205   if (option->mlpMethod == 0) {
04206     while (*startFunc != *lastFunc && *startVar != *lastVar) {
04207       found = 0;
04208       for (x = *startFunc; x <= *lastFunc; x++) {
04209         row = rowOrder[x];
04210         if (rowInfo[row].lNum == 1) {
04211           found = 1;
04212           add = MoveSingletonRow(xy, sccList, nRows, nCols, x,
04213                                 startFunc, lastFunc, startVar, lastVar,
04214                                 rowInfo, colInfo, rowOrder, colOrder,
04215                                 NIL(RcListInfo_t), option);
04216           if (*startFunc == *lastFunc || *startVar == *lastVar) {
04217             found = 0;
04218             break;
04219           }
04220           x += add;
04221         }
04222       }
04223       if (!found)
04224         break;
04225     }
04226   } else {
04227     if (*startFunc != *lastFunc && *startVar != *lastVar) {
04228       candList = SortedListAlloc();
04229       for (x = *startFunc; x <= *lastFunc; x++) {
04230         row = rowOrder[x];
04231         if (rowInfo[row].lNum == 1) {
04232           col = rowInfo[row].lMin;
04233           SortedListInsert(candList, row, col, colInfo, option->mlpMethod);
04234         }
04235       }
04236       if (option->mlpDebug)
04237         CheckSortedList(candList, colInfo, option->mlpMethod);
04238       while (candList->cur) {
04239         candList->curIndex = candList->cur->index;
04240         x = rowInfo[candList->curIndex].pos;
04241         MoveSingletonRow(xy, sccList, nRows, nCols, x,
04242                         startFunc, lastFunc, startVar, lastVar,
04243                         rowInfo, colInfo, rowOrder, colOrder,
04244                         candList, option);
04245         if (option->mlpDebug)
04246           CheckSortedList(candList, colInfo, option->mlpMethod);
04247         if (*startFunc == *lastFunc || *startVar == *lastVar) {
04248           break;
04249         }
04250       }
04251       if (option->mlpVerbosity) {
04252         fprintf(vis_stdout, "max number of elements in list = %d\n",
04253                 candList->maxNum);
04254       }
04255       SortedListFree(candList);
04256     }
04257   }
04258 }
04259 
04260 
04270 static int
04271 MoveSingletonRow(char **xy, SccList_t *sccList, int nRows, int nCols, int x,
04272         int *startFunc, int *lastFunc, int *startVar, int *lastVar,
04273         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04274         RcListInfo_t *candList, ImgTrmOption_t *option)
04275 {
04276   int   y, i, add;
04277   int   row, col, otherRow;
04278   int   startRow, lastRow, startCol, lastCol;
04279 
04280   startRow = *startFunc;
04281   startCol = *startVar;
04282   lastRow = *lastFunc;
04283   lastCol = *lastVar;
04284 
04285   row = rowOrder[x];
04286   col = rowInfo[row].lMin;
04287   y = colInfo[col].pos;
04288 
04289   if (option->mlpVerbosity >= 3) {
04290     fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (row singleton)\n",
04291           nMoves, y, col, startCol);
04292     fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
04293            startRow, lastRow, startCol, lastCol);
04294   }
04295   MoveColToLeft(xy, y, startRow, lastRow, startCol, lastCol,
04296                 rowInfo, colInfo, rowOrder, colOrder, candList,
04297                 option->mlpMethod);
04298   startCol++;
04299   if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
04300     PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
04301                 startRow, lastRow, startCol, lastCol);
04302   }
04303   if (option->mlpDebug) {
04304     CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
04305                 startRow, lastRow, startCol, lastCol, 1);
04306   }
04307 
04308   add = 0;
04309   for (i = rowInfo[colInfo[col].lMin].pos;
04310        colInfo[col].lNum && i <= rowInfo[colInfo[col].lMax].pos; i++) {
04311     otherRow = rowOrder[i];
04312     if (!xy[otherRow][col])
04313       continue;
04314     if (rowInfo[otherRow].lNum == 0) {
04315       if (option->mlpVerbosity >= 3) {
04316         fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (row singleton)\n",
04317                 nMoves, i, otherRow, startRow);
04318         fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
04319                startRow, lastRow, startCol, lastCol);
04320       }
04321       MoveRowToTop(xy, i, startRow, lastRow, startCol, lastCol,
04322                    rowInfo, colInfo, rowOrder, colOrder,
04323                    NIL(RcListInfo_t), option->mlpMethod);
04324       startRow++;
04325       if (i > x)
04326         add++;
04327       if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
04328         PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
04329                     startRow, lastRow, startCol, lastCol);
04330       }
04331       if (option->mlpDebug) {
04332         CheckMatrix(xy, sccList, nRows, nCols,
04333                     rowInfo, colInfo, rowOrder, colOrder,
04334                     startRow, lastRow, startCol, lastCol, 1);
04335       }
04336     }
04337   }
04338 
04339   *startFunc = startRow;
04340   *startVar = startCol;
04341   return(add);
04342 }
04343 
04344 
04354 static void
04355 FindAndMoveSingletonCols(char **xy, SccList_t *sccList, int nRows, int nCols,
04356         int *startFunc, int *lastFunc, int *startVar, int *lastVar,
04357         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04358         ImgTrmOption_t *option)
04359 {
04360   int           y, row, col, add, found;
04361   RcListInfo_t  *candList;
04362 
04363   if (option->mlpMethod == 0) {
04364     while (*startFunc != *lastFunc && *startVar != *lastVar) {
04365       found = 0;
04366       for (y = *startVar; y <= *lastVar; y++) {
04367         col = colOrder[y];
04368         if (colInfo[col].lNum == 1) {
04369           found = 1;
04370           add = MoveSingletonCol(xy, sccList, nRows, nCols, y,
04371                                 startFunc, lastFunc, startVar, lastVar,
04372                                 rowInfo, colInfo, rowOrder, colOrder,
04373                                 NIL(RcListInfo_t), option);
04374           if (*startFunc == *lastFunc || *startVar == *lastVar) {
04375             found = 0;
04376             break;
04377           }
04378           y -= add;
04379         }
04380       }
04381       if (!found)
04382         break;
04383     }
04384   } else {
04385     if (*startFunc != *lastFunc && *startVar != *lastVar) {
04386       candList = SortedListAlloc();
04387       for (y = *startVar; y <= *lastVar; y++) {
04388         col = colOrder[y];
04389         if (colInfo[col].lNum == 1) {
04390           row = colInfo[col].lMin;
04391           SortedListInsert(candList, col, row, rowInfo, option->mlpMethod);
04392         }
04393       }
04394       if (option->mlpDebug)
04395         CheckSortedList(candList, rowInfo, option->mlpMethod);
04396       while (candList->cur) {
04397         candList->curIndex = candList->cur->index;
04398         y = colInfo[candList->curIndex].pos;
04399         MoveSingletonCol(xy, sccList, nRows, nCols, y,
04400                         startFunc, lastFunc, startVar, lastVar,
04401                         rowInfo, colInfo, rowOrder, colOrder, candList, option);
04402         if (option->mlpDebug)
04403           CheckSortedList(candList, rowInfo, option->mlpMethod);
04404         if (*startFunc == *lastFunc || *startVar == *lastVar) {
04405           break;
04406         }
04407       }
04408       if (option->mlpVerbosity >= 2) {
04409         fprintf(vis_stdout, "max number of elements in list = %d\n",
04410                 candList->maxNum);
04411       }
04412       SortedListFree(candList);
04413     }
04414   }
04415 }
04416 
04417 
04427 static int
04428 MoveSingletonCol(char **xy, SccList_t *sccList, int nRows, int nCols, int y,
04429         int *startFunc, int *lastFunc, int *startVar, int *lastVar,
04430         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04431         RcListInfo_t *candList, ImgTrmOption_t *option)
04432 {
04433   int   x, j, add;
04434   int   row, col, otherCol;
04435   int   startRow, lastRow, startCol, lastCol;
04436 
04437   startRow = *startFunc;
04438   startCol = *startVar;
04439   lastRow = *lastFunc;
04440   lastCol = *lastVar;
04441 
04442   col = colOrder[y];
04443   row = colInfo[col].lMin;
04444   x = rowInfo[row].pos;
04445 
04446   if (option->mlpVerbosity >= 3) {
04447     fprintf(vis_stdout, "[%d] Moving Row %d(%d) to %d (col singleton)\n",
04448           nMoves, x, row, lastRow);
04449     fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
04450            startRow, lastRow, startCol, lastCol);
04451   }
04452   MoveRowToBottom(xy, x, startRow, lastRow, startCol, lastCol,
04453                   rowInfo, colInfo, rowOrder, colOrder, candList,
04454                   option->mlpMethod);
04455   lastRow--;
04456   if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
04457     PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
04458                 startRow, lastRow, startCol, lastCol);
04459   }
04460   if (option->mlpDebug) {
04461     CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
04462                 startRow, lastRow, startCol, lastCol, 1);
04463   }
04464 
04465   add = 0;
04466   for (j = colInfo[rowInfo[row].lMin].pos;
04467        rowInfo[row].lNum && j <= colInfo[rowInfo[row].lMax].pos; j++) {
04468     otherCol = colOrder[j];
04469     if (!xy[row][otherCol])
04470       continue;
04471     if (colInfo[otherCol].lNum == 0) {
04472       if (option->mlpVerbosity >= 3) {
04473         fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (col singleton)\n",
04474                 nMoves, j, otherCol, lastCol);
04475         fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
04476                 startRow, lastRow, startCol, lastCol);
04477       }
04478       MoveColToRight(xy, j, startRow, lastRow, startCol, lastCol,
04479                      rowInfo, colInfo, rowOrder, colOrder,
04480                      NIL(RcListInfo_t), option->mlpMethod);
04481       lastCol--;
04482       j--;
04483       if (otherCol <= col)
04484         add++;
04485       if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
04486         PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
04487                     startRow, lastRow, startCol, lastCol);
04488       }
04489       if (option->mlpDebug) {
04490         CheckMatrix(xy, sccList, nRows, nCols,
04491                     rowInfo, colInfo, rowOrder, colOrder,
04492                     startRow, lastRow, startCol, lastCol, 1);
04493       }
04494     }
04495   }
04496 
04497   *lastFunc = lastRow;
04498   *lastVar = lastCol;
04499   return(add);
04500 }
04501 
04502 
04512 static void
04513 MoveRowToTop(char **xy, int x, int startFunc, int lastFunc,
04514              int startVar, int lastVar, RcInfo_t *rowInfo,
04515              RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04516              RcListInfo_t *candList, int method)
04517 {
04518   int   i, j, s, t;
04519   int   row, col, tmpRow;
04520 
04521   assert(x >= startFunc && x <= lastFunc);
04522 
04523   row = rowOrder[x];
04524   if (x != startFunc) {
04525     /* Change row order */
04526     for (i = x; i > startFunc; i--) {
04527       rowOrder[i] = rowOrder[i - 1];
04528       rowInfo[rowOrder[i]].pos = i;
04529     }
04530     rowOrder[startFunc] = row;
04531     rowInfo[row].pos = startFunc;
04532   }
04533 
04534   s = colInfo[rowInfo[row].gMin].pos;
04535   t = colInfo[rowInfo[row].gMax].pos;
04536   for (j = s; j <= t; j++) {
04537     col = colOrder[j];
04538     if (!xy[row][col])
04539       continue;
04540     colInfo[col].prevG = startFunc;
04541     if (colInfo[col].lNum == 1) {
04542       colInfo[col].lMin = row;
04543       colInfo[col].lMax = row;
04544     } else {
04545       if (row == colInfo[col].lMin) {
04546         for (i = x + 1; i <= rowInfo[colInfo[col].lMax].pos; i++) {
04547           tmpRow = rowOrder[i];
04548           if (xy[tmpRow][col]) {
04549             colInfo[col].lMin = tmpRow;
04550             break;
04551           }
04552         }
04553       } else if (row == colInfo[col].lMax) {
04554         for (i = x; i >= rowInfo[colInfo[col].lMin].pos; i--) {
04555           tmpRow = rowOrder[i];
04556           if (xy[tmpRow][col]) {
04557             colInfo[col].lMax = tmpRow;
04558             break;
04559           }
04560         }
04561       }
04562     }
04563 
04564     if (colInfo[col].gNum == 1) {
04565       colInfo[col].gMin = row;
04566       colInfo[col].gMax = row;
04567     } else {
04568       if (row == colInfo[col].gMin)
04569         colInfo[col].gMin = row;
04570       else if (row == colInfo[col].gMax) {
04571         colInfo[col].gMax = colInfo[col].lMax;
04572         if (startFunc <= rowInfo[colInfo[col].gMin].pos)
04573           colInfo[col].gMin = row;
04574       } else if (startFunc <= rowInfo[colInfo[col].gMin].pos)
04575         colInfo[col].gMin = row;
04576     }
04577 
04578     if (rowInfo[row].lNum) {
04579       if (j == rowInfo[row].prevG)
04580         j = colInfo[rowInfo[row].lMin].pos - 1;
04581       else if (j == colInfo[rowInfo[row].lMax].pos)
04582         j = rowInfo[row].nextG - 1;
04583     }
04584   }
04585 
04586   s = colInfo[rowInfo[row].lMin].pos;
04587   t = colInfo[rowInfo[row].lMax].pos;
04588   for (j = s; j <= t; j++) {
04589     col = colOrder[j];
04590     if (xy[row][col]) {
04591       colInfo[col].lNum--;
04592       if (candList) {
04593         if (colInfo[col].lNum == 0)
04594           SortedListDelete(candList, col);
04595         else if (colInfo[col].lNum == 1)
04596           SortedListInsert(candList, col, row, rowInfo, method);
04597       }
04598     }
04599   }
04600 
04601   nMoves++;
04602 }
04603 
04604 
04614 static void
04615 MoveColToLeft(char **xy, int y, int startFunc, int lastFunc,
04616               int startVar, int lastVar, RcInfo_t *rowInfo,
04617               RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04618               RcListInfo_t *candList, int method)
04619 {
04620   int   i, j, s, t;
04621   int   row, col, tmpCol;
04622 
04623   assert(y >= startVar && y <= lastVar);
04624 
04625   col = colOrder[y];
04626   if (y != startVar) {
04627     /* Change col order */
04628     for (j = y; j > startVar; j--) {
04629       colOrder[j] = colOrder[j - 1];
04630       colInfo[colOrder[j]].pos = j;
04631     }
04632     colOrder[startVar] = col;
04633     colInfo[col].pos = startVar;
04634   }
04635 
04636   s = rowInfo[colInfo[col].gMin].pos;
04637   t = rowInfo[colInfo[col].gMax].pos;
04638   for (i = s; i <= t; i++) {
04639     row = rowOrder[i];
04640     if (!xy[row][col])
04641       continue;
04642     rowInfo[row].prevG = startVar;
04643     if (rowInfo[row].lNum == 1) {
04644       rowInfo[row].lMin = col;
04645       rowInfo[row].lMax = col;
04646     } else {
04647       if (col == rowInfo[row].lMin) {
04648         for (j = y + 1; j <= colInfo[rowInfo[row].lMax].pos; j++) {
04649           tmpCol = colOrder[j];
04650           if (xy[row][tmpCol]) {
04651             rowInfo[row].lMin = tmpCol;
04652             break;
04653           }
04654         }
04655       } else if (col == rowInfo[row].lMax) {
04656         for (j = y; j >= colInfo[rowInfo[row].lMin].pos; j--) {
04657           tmpCol = colOrder[j];
04658           if (xy[row][tmpCol]) {
04659             rowInfo[row].lMax = tmpCol;
04660             break;
04661           }
04662         }
04663       }
04664     }
04665 
04666     if (rowInfo[row].gNum == 1) {
04667       rowInfo[row].gMin = col;
04668       rowInfo[row].gMax = col;
04669     } else {
04670       if (col == rowInfo[row].gMin)
04671         rowInfo[row].gMin = col;
04672       else if (col == rowInfo[row].gMax) {
04673         rowInfo[row].gMax = rowInfo[row].lMax;
04674         if (startVar <= colInfo[rowInfo[row].gMin].pos)
04675           rowInfo[row].gMin = col;
04676       } else if (startVar <= colInfo[rowInfo[row].gMin].pos)
04677         rowInfo[row].gMin = col;
04678     }
04679 
04680     if (colInfo[col].lNum) {
04681       if (i == colInfo[col].prevG)
04682         i = rowInfo[colInfo[col].lMin].pos - 1;
04683       else if (i == rowInfo[colInfo[col].lMax].pos)
04684         i = colInfo[col].nextG - 1;
04685     }
04686   }
04687 
04688   s = rowInfo[colInfo[col].lMin].pos;
04689   t = rowInfo[colInfo[col].lMax].pos;
04690   for (i = s; i <= t; i++) {
04691     row = rowOrder[i];
04692     if (xy[row][col]) {
04693       rowInfo[row].lNum--;
04694       if (candList) {
04695         if (rowInfo[row].lNum == 0)
04696           SortedListDelete(candList, row);
04697         else if (rowInfo[row].lNum == 1)
04698           SortedListInsert(candList, row, col, colInfo, method);
04699       }
04700     }
04701   }
04702 
04703   nMoves++;
04704 }
04705 
04706 
04716 static void
04717 MoveRowToBottom(char **xy, int x, int startFunc, int lastFunc,
04718                 int startVar, int lastVar, RcInfo_t *rowInfo,
04719                 RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04720                 RcListInfo_t *candList, int method)
04721 {
04722   int   i, j, s, t;
04723   int   row, col, tmpRow;
04724 
04725   assert(x >= startFunc && x <= lastFunc);
04726 
04727   row = rowOrder[x];
04728   if (x != lastFunc) {
04729     /* Change row order */
04730     for (i = x; i < lastFunc; i++) {
04731       rowOrder[i] = rowOrder[i + 1];
04732       rowInfo[rowOrder[i]].pos = i;
04733     }
04734     rowOrder[lastFunc] = row;
04735     rowInfo[row].pos = lastFunc;
04736   }
04737 
04738   s = colInfo[rowInfo[row].gMin].pos;
04739   t = colInfo[rowInfo[row].gMax].pos;
04740   for (j = s; j <= t; j++) {
04741     col = colOrder[j];
04742     if (!xy[row][col])
04743       continue;
04744     colInfo[col].nextG = lastFunc;
04745     if (colInfo[col].lNum == 1) {
04746       colInfo[col].lMin = row;
04747       colInfo[col].lMax = row;
04748     } else {
04749       if (row == colInfo[col].lMin) {
04750         for (i = x; i <= rowInfo[colInfo[col].lMax].pos; i++) {
04751           tmpRow = rowOrder[i];
04752           if (xy[tmpRow][col]) {
04753             colInfo[col].lMin = tmpRow;
04754             break;
04755           }
04756         }
04757       } else if (row == colInfo[col].lMax) {
04758         for (i = x - 1; i >= rowInfo[colInfo[col].lMin].pos; i--) {
04759           tmpRow = rowOrder[i];
04760           if (xy[tmpRow][col]) {
04761             colInfo[col].lMax = tmpRow;
04762             break;
04763           }
04764         }
04765       }
04766     }
04767 
04768     if (colInfo[col].gNum == 1) {
04769       colInfo[col].gMin = row;
04770       colInfo[col].gMax = row;
04771     } else {
04772       if (row == colInfo[col].gMax)
04773         colInfo[col].gMax = row;
04774       else if (row == colInfo[col].gMin) {
04775         colInfo[col].gMin = colInfo[col].lMin;
04776         if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
04777           colInfo[col].gMax = row;
04778       } else if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
04779         colInfo[col].gMax = row;
04780     }
04781 
04782     if (rowInfo[row].lNum) {
04783       if (j == rowInfo[row].prevG)
04784         j = colInfo[rowInfo[row].lMin].pos - 1;
04785       else if (j == colInfo[rowInfo[row].lMax].pos)
04786         j = rowInfo[row].nextG - 1;
04787     }
04788   }
04789 
04790   s = colInfo[rowInfo[row].lMin].pos;
04791   t = colInfo[rowInfo[row].lMax].pos;
04792   for (j = s; j <= t; j++) {
04793     col = colOrder[j];
04794     if (xy[row][col]) {
04795       colInfo[col].lNum--;
04796       if (candList) {
04797         if (colInfo[col].lNum == 0)
04798           SortedListDelete(candList, col);
04799         else if (colInfo[col].lNum == 1)
04800           SortedListInsert(candList, col, row, rowInfo, method);
04801       }
04802     }
04803   }
04804 
04805   nMoves++;
04806 }
04807 
04808 
04818 static void
04819 MoveColToRight(char **xy, int y, int startFunc, int lastFunc,
04820                int startVar, int lastVar, RcInfo_t *rowInfo,
04821                RcInfo_t *colInfo, int *rowOrder, int *colOrder,
04822                RcListInfo_t *candList, int method)
04823 {
04824   int   i, j, s, t;
04825   int   row, col, tmpCol;
04826 
04827   assert(y >= startVar && y <= lastVar);
04828 
04829   col = colOrder[y];
04830   if (y != lastVar) {
04831     /* Change col order */
04832     for (j = y; j < lastVar; j++) {
04833       colOrder[j] = colOrder[j + 1];
04834       colInfo[colOrder[j]].pos = j;
04835     }
04836     colOrder[lastVar] = col;
04837     colInfo[col].pos = lastVar;
04838   }
04839 
04840   s = rowInfo[colInfo[col].gMin].pos;
04841   t = rowInfo[colInfo[col].gMax].pos;
04842   for (i = s; i <= t; i++) {
04843     row = rowOrder[i];
04844     if (!xy[row][col])
04845       continue;
04846     rowInfo[row].nextG = lastVar;
04847     if (rowInfo[row].lNum == 1) {
04848       rowInfo[row].lMin = col;
04849       rowInfo[row].lMax = col;
04850     } else {
04851       if (col == rowInfo[row].lMin) {
04852         for (j = y; j <= colInfo[rowInfo[row].lMax].pos; j++) {
04853           tmpCol = colOrder[j];
04854           if (xy[row][tmpCol]) {
04855             rowInfo[row].lMin = tmpCol;
04856             break;
04857           }
04858         }
04859       } else if (col == rowInfo[row].lMax) {
04860         for (j = y - 1; j >= colInfo[rowInfo[row].lMin].pos; j--) {
04861           tmpCol = colOrder[j];
04862           if (xy[row][tmpCol]) {
04863             rowInfo[row].lMax = tmpCol;
04864             break;
04865           }
04866         }
04867       }
04868     }
04869 
04870     if (rowInfo[row].gNum == 1) {
04871       rowInfo[row].gMin = col;
04872       rowInfo[row].gMax = col;
04873     } else {
04874       if (col == rowInfo[row].gMax)
04875         rowInfo[row].gMax = col;
04876       else if (col == rowInfo[row].gMin) {
04877         rowInfo[row].gMin = rowInfo[row].lMin;
04878         if (lastVar >= colInfo[rowInfo[row].gMax].pos)
04879           rowInfo[row].gMax = col;
04880       } else if (lastVar >= colInfo[rowInfo[row].gMax].pos)
04881         rowInfo[row].gMax = col;
04882     }
04883 
04884     if (colInfo[col].lNum) {
04885       if (i == colInfo[col].prevG)
04886         i = rowInfo[colInfo[col].lMin].pos - 1;
04887       else if (i == rowInfo[colInfo[col].lMax].pos)
04888         i = colInfo[col].nextG - 1;
04889     }
04890   }
04891 
04892   s = rowInfo[colInfo[col].lMin].pos;
04893   t = rowInfo[colInfo[col].lMax].pos;
04894   for (i = s; i <= t; i++) {
04895     row = rowOrder[i];
04896     if (xy[row][col]) {
04897       rowInfo[row].lNum--;
04898       if (candList) {
04899         if (rowInfo[row].lNum == 0)
04900           SortedListDelete(candList, row);
04901         else if (rowInfo[row].lNum == 1)
04902           SortedListInsert(candList, row, col, colInfo, method);
04903       }
04904     }
04905   }
04906 
04907   nMoves++;
04908 }
04909 
04910 
04920 static void
04921 PrintMatrix(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
04922             RcInfo_t *rowInfo, RcInfo_t *colInfo,
04923             int startFunc, int lastFunc, int startVar, int lastVar)
04924 {
04925   int   i, j, x, y;
04926   int   row, col, index;
04927   char  line[2048];
04928   bdd_t *nsVar;
04929 
04930   line[nCols] = '\0';
04931   for (x = 0; x < nRows; x++) {
04932     if (startFunc != lastFunc && startVar != lastVar &&
04933         x == startFunc && x != 0) {
04934       for (y = 0; y < nCols; y++) {
04935         if (y == startVar || y == lastVar)
04936           line[y] = '%';
04937         else
04938           line[y] = '=';
04939       }
04940       fprintf(vis_stdout, "%s\n", line);
04941     }
04942     i = rowOrder[x];
04943     for (y = 0; y < nCols; y++) {
04944       j = colOrder[y];
04945       if (xy[i][j])
04946         line[y] = '1';
04947       else
04948         line[y] = '.';
04949     }
04950     fprintf(vis_stdout, "%s\n", line);
04951     if (startFunc != lastFunc && startVar != lastVar &&
04952         x == lastFunc && x < nRows - 1) {
04953       for (y = 0; y < nCols; y++) {
04954         if (y == startVar || y == lastVar)
04955           line[y] = '%';
04956         else
04957           line[y] = '=';
04958       }
04959       fprintf(vis_stdout, "%s\n", line);
04960     }
04961   }
04962   fprintf(vis_stdout, "row order :");
04963   for (x = 0; x < nRows; x++) {
04964     row = rowOrder[x];
04965     fprintf(vis_stdout, " %d(", row);
04966     if (rowInfo[row].data.row.nsVarBddArray) {
04967       for (i = 0; i < array_n(rowInfo[row].data.row.nsVarBddArray); i++) {
04968         nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, i);
04969         index = (int)bdd_top_var_id(nsVar);
04970         if (i == 0)
04971           fprintf(vis_stdout, "%d", index);
04972         else
04973           fprintf(vis_stdout, ",%d", index);
04974       }
04975     }
04976     fprintf(vis_stdout, ")");
04977   }
04978   fprintf(vis_stdout, "\n");
04979   fprintf(vis_stdout, "col order :");
04980   for (y = 0; y < nCols; y++) {
04981     col = colOrder[y];
04982     index = (int)bdd_top_var_id(colInfo[col].data.col.var);
04983     fprintf(vis_stdout, " %d(%d)", col, index);
04984   }
04985   fprintf(vis_stdout, "\n");
04986   fprintf(vis_stdout, "#active rows : %d-%d\n", startFunc, lastFunc);
04987   fprintf(vis_stdout, "#active cols : %d-%d\n", startVar, lastVar);
04988 }
04989 
04990 
05000 static void
05001 PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols,
05002                         int *rowOrder, int *colOrder,
05003                         Img_DirectionType direction)
05004 {
05005   int           i, j, x, y;
05006   char          line[2048];
05007   ClusterList_t *list, *tailCluster;
05008 
05009   line[nCols] = '\0';
05010   if (direction == Img_Forward_c) {
05011     tailCluster = headCluster;
05012     list = headCluster;
05013     while (list->next) {
05014       tailCluster = list->next;
05015       list = tailCluster;
05016     }
05017     list = tailCluster;
05018     while (list) {
05019       for (x = list->start; x <= list->end; x++) {
05020         i = rowOrder[x];
05021         for (y = 0; y < nCols; y++) {
05022           j = colOrder[y];
05023           if (xy[i][j])
05024             line[y] = '1';
05025           else
05026             line[y] = '.';
05027         }
05028         fprintf(vis_stdout, "%s\n", line);
05029       }
05030       list = list->prev;
05031       if (list) {
05032         for (y = 0; y < nCols; y++)
05033           line[y] = '-';
05034         fprintf(vis_stdout, "%s\n", line);
05035       }
05036     }
05037   } else {
05038     list = headCluster;
05039     while (list) {
05040       for (x = list->start; x <= list->end; x++) {
05041         i = rowOrder[x];
05042         for (y = 0; y < nCols; y++) {
05043           j = colOrder[y];
05044           if (xy[i][j])
05045             line[y] = '1';
05046           else
05047             line[y] = '.';
05048         }
05049         fprintf(vis_stdout, "%s\n", line);
05050       }
05051       list = list->next;
05052       if (list) {
05053         for (y = 0; y < nCols; y++)
05054           line[y] = '-';
05055         fprintf(vis_stdout, "%s\n", line);
05056       }
05057     }
05058   }
05059 }
05060 
05061 
05071 static void
05072 PrintClusterMatrix(ClusterList_t *headCluster, int nCols,
05073                    int *colOrder, Img_DirectionType direction)
05074 {
05075   int           j, y;
05076   char          line[2048];
05077   ClusterList_t *list, *tailCluster;
05078 
05079   line[nCols] = '\0';
05080   if (direction == Img_Forward_c) {
05081     tailCluster = headCluster;
05082     list = headCluster;
05083     while (list->next) {
05084       tailCluster = list->next;
05085       list = tailCluster;
05086     }
05087     list = tailCluster;
05088     while (list) {
05089       for (y = 0; y < nCols; y++) {
05090         j = colOrder[y];
05091         if (list->supports[j])
05092           line[y] = '1';
05093         else
05094           line[y] = '.';
05095       }
05096       fprintf(vis_stdout, "%s\n", line);
05097       list = list->prev;
05098       if (list) {
05099         for (y = 0; y < nCols; y++)
05100           line[y] = '-';
05101         fprintf(vis_stdout, "%s\n", line);
05102       }
05103     }
05104   } else {
05105     list = headCluster;
05106     while (list) {
05107       for (y = 0; y < nCols; y++) {
05108         j = colOrder[y];
05109         if (list->supports[j])
05110           line[y] = '1';
05111         else
05112           line[y] = '.';
05113       }
05114       fprintf(vis_stdout, "%s\n", line);
05115       list = list->next;
05116       if (list) {
05117         for (y = 0; y < nCols; y++)
05118           line[y] = '-';
05119         fprintf(vis_stdout, "%s\n", line);
05120       }
05121     }
05122   }
05123 }
05124 
05125 
05135 static void
05136 CheckMatrix(char **xy, SccList_t *sccList, int nRows, int nCols,
05137             RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
05138             int startFunc, int lastFunc, int startVar, int lastVar, int local)
05139 {
05140   int   i, j, x, y;
05141   int   lMin, lMax, gMin, gMax, lNum, gNum, prevG, nextG;
05142   int   error = 0;
05143 
05144   for (x = 0; x < nRows; x++) {
05145     i = rowOrder[x];
05146     if (x != rowInfo[i].pos) {
05147       fprintf(vis_stderr, "Error : wrong rowOrder (%d != %d) in Row %d\n",
05148              x, rowInfo[i].pos, x);
05149       error = 1;
05150     }
05151 
05152     lMin = gMin = nCols;
05153     lMax = gMax = -1;
05154     lNum = gNum = 0;
05155     prevG = -1;
05156     nextG = nCols;
05157 
05158     for (y = 0; y < nCols; y++) {
05159       j = colOrder[y];
05160       if (xy[i][j]) {
05161         gNum++;
05162         if (y < gMin)
05163           gMin = y;
05164         if (y > gMax)
05165           gMax = y;
05166         if (local) {
05167           if (x >= startFunc && x <= lastFunc &&
05168               y >= startVar && y <= lastVar) {
05169             if (y < lMin)
05170               lMin = y;
05171             if (y > lMax)
05172               lMax = y;
05173             lNum++;
05174           }
05175           if (!sccList ||
05176               (x >= sccList->startFunc && x <= sccList->lastFunc)) {
05177             if (y < startVar)
05178               prevG = y;
05179             if (y > lastVar && nextG == nCols)
05180               nextG = y;
05181           }
05182         }
05183       }
05184     }
05185     if (gNum != rowInfo[i].gNum) {
05186       fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Row %d\n",
05187              gNum, rowInfo[i].gNum, x);
05188       error = 1;
05189     }
05190     if (gNum > 0) {
05191       if (gMin != colInfo[rowInfo[i].gMin].pos) {
05192         fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Row %d\n",
05193                gMin, colInfo[rowInfo[i].gMin].pos, x);
05194         error = 1;
05195       }
05196       if (gMax != colInfo[rowInfo[i].gMax].pos) {
05197         fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Row %d\n",
05198                gMax, colInfo[rowInfo[i].gMax].pos, x);
05199         error = 1;
05200       }
05201     }
05202     if (local) {
05203       if (x >= startFunc && x <= lastFunc &&
05204           lNum != rowInfo[i].lNum) {
05205         fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Row %d\n",
05206                lNum, rowInfo[i].lNum, x);
05207         error = 1;
05208       }
05209       if (x >= startFunc && x <= lastFunc && lMin < nCols &&
05210           lMin != colInfo[rowInfo[i].lMin].pos) {
05211         fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Row %d\n",
05212                lMin, colInfo[rowInfo[i].lMin].pos, x);
05213         error = 1;
05214       }
05215       if (x >= startFunc && x <= lastFunc && lMax > -1 &&
05216           lMax != colInfo[rowInfo[i].lMax].pos) {
05217         fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Row %d\n",
05218                lMax, colInfo[rowInfo[i].lMax].pos, x);
05219         error = 1;
05220       }
05221       if (!sccList || (x >= sccList->startFunc && x <= sccList->lastFunc)) {
05222         if (prevG != rowInfo[i].prevG) {
05223           fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Row %d\n",
05224                   prevG, rowInfo[i].prevG, x);
05225           error = 1;
05226         }
05227         if (nextG != rowInfo[i].nextG) {
05228           fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Row %d\n",
05229                   nextG, rowInfo[i].nextG, x);
05230           error = 1;
05231         }
05232       }
05233     }
05234   }
05235 
05236   for (y = 0; y < nCols; y++) {
05237     j = colOrder[y];
05238     if (y != colInfo[j].pos) {
05239       fprintf(vis_stderr, "Error : wrong colOrder (%d != %d) in Col %d\n",
05240              y, colInfo[y].pos, y);
05241       error = 1;
05242     }
05243 
05244     lMin = gMin = nRows;
05245     lMax = gMax = -1;
05246     lNum = gNum = 0;
05247     prevG = -1;
05248     nextG = nRows;
05249 
05250     for (x = 0; x < nRows; x++) {
05251       i = rowOrder[x];
05252       if (xy[i][j]) {
05253         gNum++;
05254         if (x < gMin)
05255           gMin = x;
05256         if (x > gMax)
05257           gMax = x;
05258         if (local) {
05259           if (x >= startFunc && x <= lastFunc &&
05260               y >= startVar && y <= lastVar) {
05261             if (x < lMin)
05262               lMin = x;
05263             if (x > lMax)
05264               lMax = x;
05265             lNum++;
05266           }
05267           if (!sccList ||
05268               (y >= sccList->startVar && y <= sccList->lastVar)) {
05269             if (x < startFunc)
05270               prevG = x;
05271             if (x > lastFunc && nextG == nRows)
05272               nextG = x;
05273           }
05274         }
05275       }
05276     }
05277     if (gNum != colInfo[j].gNum) {
05278       fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Col %d\n",
05279              gNum, colInfo[j].gNum, y);
05280       error = 1;
05281     }
05282     if (gNum > 0) {
05283       if (gMin != rowInfo[colInfo[j].gMin].pos) {
05284         fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Col %d\n",
05285                gMin, rowInfo[colInfo[j].gMin].pos, y);
05286         error = 1;
05287       }
05288       if (gMax != rowInfo[colInfo[j].gMax].pos) {
05289         fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Col %d\n",
05290                gMax, rowInfo[colInfo[j].gMax].pos, y);
05291         error = 1;
05292       }
05293     }
05294     if (local) {
05295       if (y >= startVar && y <= lastVar &&
05296           lNum != colInfo[j].lNum) {
05297         fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Col %d\n",
05298                lNum, colInfo[j].lNum, y);
05299         error = 1;
05300       }
05301       if (y >= startVar && y <= lastVar && lMin < nRows &&
05302           lMin != rowInfo[colInfo[j].lMin].pos) {
05303         fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Col %d\n",
05304                lMin, rowInfo[colInfo[j].lMin].pos, y);
05305         error = 1;
05306       }
05307       if (y >= startVar && y <= lastVar && lMax > -1 &&
05308           lMax != rowInfo[colInfo[j].lMax].pos) {
05309         fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Col %d\n",
05310                lMax, rowInfo[colInfo[j].lMax].pos, y);
05311         error = 1;
05312       }
05313       if (!sccList || (y >= sccList->startVar && y <= sccList->lastVar)) {
05314         if (prevG != colInfo[j].prevG) {
05315           fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Col %d\n",
05316                   prevG, colInfo[j].prevG, y);
05317           error = 1;
05318         }
05319         if (nextG != colInfo[j].nextG) {
05320           fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Col %d\n",
05321                   nextG, colInfo[j].nextG, y);
05322           error = 1;
05323         }
05324       }
05325     }
05326   }
05327 
05328   assert(!error);
05329 }
05330 
05331 
05341 static void
05342 CheckCluster(ClusterList_t *headCluster, int nCols,
05343                 RcInfo_t *colInfo, int *colOrder)
05344 {
05345   int   j, y, n;
05346   int   gMin, gMax, gNum;
05347   int   error = 0;
05348   ClusterList_t *list;
05349 
05350   n = 0;
05351   list = headCluster;
05352   while (list) {
05353     gMin = nCols;
05354     gMax = -1;
05355     gNum = 0;
05356 
05357     for (y = 0; y < nCols; y++) {
05358       j = colOrder[y];
05359       if (list->supports[j]) {
05360         gNum++;
05361         if (y < gMin)
05362           gMin = y;
05363         if (y > gMax)
05364           gMax = y;
05365       }
05366     }
05367     if (gNum != list->nSupports) {
05368       fprintf(vis_stderr, "Error : wrong nSupports (%d != %d) in Cluster %d\n",
05369              gNum, list->nSupports, n);
05370       error = 1;
05371     }
05372     if (gNum > 0) {
05373       if (gMin != colInfo[list->minCol].pos) {
05374         fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Cluster %d\n",
05375                gMin, colInfo[list->minCol].pos, n);
05376         error = 1;
05377       }
05378       if (gMax != colInfo[list->maxCol].pos) {
05379         fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Cluster %d\n",
05380                gMax, colInfo[list->maxCol].pos, n);
05381         error = 1;
05382       }
05383     }
05384     n++;
05385     list = list->next;
05386   }
05387 
05388   assert(!error);
05389 }
05390 
05391 
05401 static void
05402 WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder,
05403             int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo)
05404 {
05405   int   x, y;
05406   int   row, col;
05407 
05408   for (x = 0; x < nRows; x++) {
05409     row = rowOrder[x];
05410     for (y = 0; y < nCols; y++) {
05411       col = colOrder[y];
05412       if (xy[row][col])
05413         fprintf(fout, "%d %d %d\n", y, x, colInfo[col].data.col.type);
05414     }
05415   }
05416 }
05417 
05418 
05428 static void
05429 PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
05430          int from, int to)
05431 {
05432   int   x, y, row, col;
05433 
05434   for (x = from; x <= to; x++) {
05435     row = rowOrder[x];
05436     fprintf(vis_stdout, "[%d]%d :", x, row);
05437     for (y = 0; y < nCols; y++) {
05438       col = colOrder[y];
05439       if (xy[row][col])
05440         fprintf(vis_stdout, " %d(%d)", y, col);
05441     }
05442     fprintf(vis_stdout, "\n");
05443   }
05444 }
05445 
05446 
05456 static void
05457 PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
05458          int from, int to)
05459 {
05460   int   x, y, row, col;
05461 
05462   for (y = from; y <= to; y++) {
05463     col = colOrder[y];
05464     fprintf(vis_stdout, "[%d]%d :", y, col);
05465     for (x = 0; x < nRows; x++) {
05466       row = rowOrder[x];
05467       if (xy[row][col])
05468         fprintf(vis_stdout, " %d(%d)", x, row);
05469     }
05470     fprintf(vis_stdout, "\n");
05471   }
05472 }
05473 
05474 
05484 static RcListInfo_t *
05485 SortedListAlloc(void)
05486 {
05487   RcListInfo_t  *listInfo;
05488 
05489   listInfo = ALLOC(RcListInfo_t, 1);
05490   memset(listInfo, 0, sizeof(RcListInfo_t));
05491   listInfo->table = st_init_table(st_numcmp, st_numhash);
05492   return(listInfo);
05493 }
05494 
05495 
05505 static void
05506 SortedListFree(RcListInfo_t *candList)
05507 {
05508   RcList_t      *candidate, *next;
05509 
05510   candidate = candList->head;
05511   while (candidate) {
05512     next = candidate->next;
05513     FREE(candidate);
05514     candidate = next;
05515   }
05516   st_free_table(candList->table);
05517   FREE(candList);
05518 }
05519 
05520 
05530 static void
05531 SortedListInsert(RcListInfo_t *candList, int index,
05532                  int otherIndex, RcInfo_t *otherInfo, int method)
05533 {
05534   RcList_t      *candidate, *cur;
05535   int           lNum, gNum, diffH, diffT;
05536 
05537   candidate = ALLOC(RcList_t, 1);
05538   candidate->index = index;
05539   candidate->otherIndex = otherIndex;
05540   st_insert(candList->table, (char *)(long)index, (char *)candidate);
05541 
05542   if (candList->num == 0) {
05543     candidate->next = NIL(RcList_t);
05544     candidate->prev = NIL(RcList_t);
05545     candList->cur = candidate;
05546     candList->head = candidate;
05547     candList->tail = candidate;
05548     candList->num = 1;
05549     candList->maxNum = 1;
05550     return;
05551   }
05552 
05553   candList->num++;
05554   if (candList->num > candList->maxNum)
05555     candList->maxNum = candList->num;
05556 
05557   if (method == 1) {
05558     diffH = abs(index - candList->head->index);
05559     diffT = abs(index - candList->tail->index);
05560 
05561     if (diffH < diffT) {
05562       cur = candList->head;
05563       while (cur) {
05564         if (index < cur->index) {
05565           candidate->next = cur;
05566           candidate->prev = cur->prev;
05567           if (cur->prev)
05568             cur->prev->next = candidate;
05569           cur->prev = candidate;
05570           if (cur == candList->head)
05571             candList->head = candidate;
05572           break;
05573         }
05574         cur = cur->next;
05575       }
05576       if (!cur) {
05577         candidate->next = NIL(RcList_t);
05578         candidate->prev = candList->tail;
05579         candList->tail->next = candidate;
05580         candList->tail = candidate;
05581       }
05582     } else {
05583       cur = candList->tail;
05584       while (cur) {
05585         if (index > cur->index) {
05586           candidate->next = cur->next;
05587           if (cur->next)
05588             cur->next->prev = candidate;
05589           candidate->prev = cur;
05590           cur->next = candidate;
05591           if (cur == candList->tail)
05592             candList->tail = candidate;
05593           break;
05594         }
05595         cur = cur->prev;
05596       }
05597       if (!cur) {
05598         candidate->next = candList->head;
05599         candidate->prev = NIL(RcList_t);
05600         candList->head->prev = candidate;
05601         candList->head = candidate;
05602       }
05603     }
05604 
05605     if (candList->cur) {
05606       if (candList->cur->index == candList->curIndex)
05607         return;
05608       else if (candList->cur->index > candList->curIndex) {
05609         cur = candList->cur->prev;
05610         while (cur) {
05611           if (cur->index <= candList->curIndex)
05612             break;
05613           candList->cur = cur;
05614           cur = cur->prev;
05615         }
05616       } else {
05617         if (candidate->index > candList->curIndex)
05618           candList->cur = candidate;
05619         else
05620           candList->cur = candList->head;
05621       }
05622     } else
05623       candList->cur = candList->head;
05624   } else if (method == 2) {
05625     lNum = otherInfo[otherIndex].lNum;
05626     gNum = otherInfo[otherIndex].gNum;
05627     diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
05628     diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
05629 
05630     if (diffH < diffT) {
05631       cur = candList->head;
05632       while (cur) {
05633         if (lNum < otherInfo[cur->otherIndex].lNum ||
05634             (lNum == otherInfo[cur->otherIndex].lNum &&
05635              (gNum < otherInfo[cur->otherIndex].gNum ||
05636               (gNum == otherInfo[cur->otherIndex].gNum &&
05637                 index < cur->index)))) {
05638           candidate->next = cur;
05639           candidate->prev = cur->prev;
05640           if (cur->prev)
05641             cur->prev->next = candidate;
05642           cur->prev = candidate;
05643           if (cur == candList->head)
05644             candList->head = candidate;
05645           break;
05646         }
05647         cur = cur->next;
05648       }
05649       if (!cur) {
05650         candidate->next = NIL(RcList_t);
05651         candidate->prev = candList->tail;
05652         candList->tail->next = candidate;
05653         candList->tail = candidate;
05654       }
05655     } else {
05656       cur = candList->tail;
05657       while (cur) {
05658         if (lNum > otherInfo[cur->otherIndex].lNum ||
05659             (lNum == otherInfo[cur->otherIndex].lNum &&
05660              (gNum > otherInfo[cur->otherIndex].gNum ||
05661               (gNum == otherInfo[cur->otherIndex].gNum &&
05662                 index > cur->index)))) {
05663           candidate->next = cur->next;
05664           if (cur->next)
05665             cur->next->prev = candidate;
05666           candidate->prev = cur;
05667           cur->next = candidate;
05668           if (cur == candList->tail)
05669             candList->tail = candidate;
05670           break;
05671         }
05672         cur = cur->prev;
05673       }
05674       if (!cur) {
05675         candidate->next = candList->head;
05676         candidate->prev = NIL(RcList_t);
05677         candList->head->prev = candidate;
05678         candList->head = candidate;
05679       }
05680     }
05681   } else if (method == 3) {
05682     lNum = otherInfo[otherIndex].lNum;
05683     gNum = otherInfo[otherIndex].gNum;
05684     diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
05685     diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
05686 
05687     if (diffH < diffT) {
05688       cur = candList->head;
05689       while (cur) {
05690         if (lNum < otherInfo[cur->otherIndex].lNum ||
05691             (lNum == otherInfo[cur->otherIndex].lNum &&
05692              (gNum > otherInfo[cur->otherIndex].gNum ||
05693               (gNum == otherInfo[cur->otherIndex].gNum &&
05694                 otherInfo[index].pos < otherInfo[cur->index].pos)))) {
05695           candidate->next = cur;
05696           candidate->prev = cur->prev;
05697           if (cur->prev)
05698             cur->prev->next = candidate;
05699           cur->prev = candidate;
05700           if (cur == candList->head)
05701             candList->head = candidate;
05702           break;
05703         }
05704         cur = cur->next;
05705       }
05706       if (!cur) {
05707         candidate->next = NIL(RcList_t);
05708         candidate->prev = candList->tail;
05709         candList->tail->next = candidate;
05710         candList->tail = candidate;
05711       }
05712     } else {
05713       cur = candList->tail;
05714       while (cur) {
05715         if (lNum > otherInfo[cur->otherIndex].lNum ||
05716             (lNum == otherInfo[cur->otherIndex].lNum &&
05717              (gNum < otherInfo[cur->otherIndex].gNum ||
05718               (gNum == otherInfo[cur->otherIndex].gNum &&
05719                 otherInfo[index].pos > otherInfo[cur->index].pos)))) {
05720           candidate->next = cur->next;
05721           if (cur->next)
05722             cur->next->prev = candidate;
05723           candidate->prev = cur;
05724           cur->next = candidate;
05725           if (cur == candList->tail)
05726             candList->tail = candidate;
05727           break;
05728         }
05729         cur = cur->prev;
05730       }
05731       if (!cur) {
05732         candidate->next = candList->head;
05733         candidate->prev = NIL(RcList_t);
05734         candList->head->prev = candidate;
05735         candList->head = candidate;
05736       }
05737     }
05738   } else if (method == 4) {
05739     lNum = otherInfo[index].lNum;
05740     cur = candList->tail;
05741     while (cur) {
05742       if (cur->otherIndex > 1 ||
05743           (cur->otherIndex == 1 && otherInfo[cur->index].lNum > lNum) ||
05744           (cur->otherIndex == 1 && otherInfo[cur->index].lNum == lNum &&
05745            otherInfo[index].pos > otherInfo[cur->index].pos)) {
05746         candidate->next = cur->next;
05747         if (cur->next)
05748           cur->next->prev = candidate;
05749         candidate->prev = cur;
05750         cur->next = candidate;
05751         if (cur == candList->tail)
05752           candList->tail = candidate;
05753         break;
05754       }
05755       cur = cur->prev;
05756     }
05757     if (!cur) {
05758       candidate->next = candList->head;
05759       candidate->prev = NIL(RcList_t);
05760       candList->head->prev = candidate;
05761       candList->head = candidate;
05762     }
05763   } else {
05764     fprintf(vis_stderr, "** mlp error: invalid sort mode %d\n", method);
05765   }
05766 
05767   candList->cur = candList->head;
05768 }
05769 
05770 
05780 static void
05781 SortedListDelete(RcListInfo_t *candList, int index)
05782 {
05783   RcList_t      *candidate;
05784   long          lindex = (long) index;
05785 
05786   if (st_lookup(candList->table, (char *)lindex, &candidate)) {
05787     if (candidate == candList->head)
05788       candList->head = candidate->next;
05789     else
05790       candidate->prev->next = candidate->next;
05791     if (candidate == candList->tail)
05792       candList->tail = candidate->prev;
05793     else
05794       candidate->next->prev = candidate->prev;
05795     if (candidate == candList->cur) {
05796       if (candidate->next)
05797         candList->cur = candidate->next;
05798       else
05799         candList->cur = candList->head;
05800     }
05801     st_delete(candList->table, &lindex, NULL);
05802     candList->num--;
05803     FREE(candidate);
05804   }
05805 }
05806 
05807 
05817 static void
05818 SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method)
05819 {
05820   RcList_t      *cur, *prev, *left, *right;
05821 
05822   if (st_lookup(candList->table, (char *)(long)index, &cur)) {
05823     if (method == 1) {
05824     } else if (method == 2) {
05825     } else if (method == 3) {
05826       while (cur != candList->head) {
05827         prev = cur->prev;
05828         if (info[prev->index].lNum < info[cur->index].lNum ||
05829             (info[prev->index].lNum == info[cur->index].lNum &&
05830              (info[prev->index].gNum > info[cur->index].gNum ||
05831               (info[prev->index].gNum == info[cur->index].gNum &&
05832                 info[prev->index].pos < info[cur->index].pos)))) {
05833           break;
05834         }
05835 
05836         /* swap */
05837         if (prev == candList->head)
05838           candList->head = cur;
05839         if (cur == candList->tail)
05840           candList->tail = prev;
05841         left = prev->prev;
05842         right = cur->next;
05843         if (left)
05844           left->next = cur;
05845         cur->next = prev;
05846         prev->next = right;
05847         if (right)
05848           right->prev = prev;
05849         prev->prev = cur;
05850         cur->prev = left;
05851       }
05852     } else if (method == 4) {
05853       while (cur != candList->head) {
05854         prev = cur->prev;
05855         if (prev->otherIndex > cur->otherIndex ||
05856             (prev->otherIndex == cur->otherIndex &&
05857              (info[prev->index].lNum > info[cur->index].lNum ||
05858               (info[prev->index].lNum == info[cur->index].lNum &&
05859                 info[prev->index].pos < info[cur->index].pos)))) {
05860           break;
05861         }
05862 
05863         /* swap */
05864         if (prev == candList->head)
05865           candList->head = cur;
05866         if (cur == candList->tail)
05867           candList->tail = prev;
05868         left = prev->prev;
05869         right = cur->next;
05870         if (left)
05871           left->next = cur;
05872         cur->next = prev;
05873         prev->next = right;
05874         if (right)
05875           right->prev = prev;
05876         prev->prev = cur;
05877         cur->prev = left;
05878       }
05879     }
05880   }
05881 }
05882 
05883 
05893 static void
05894 CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method)
05895 {
05896   RcList_t      *cur, *next, *candidate;
05897   int           error = 0;
05898   int           num = 0;
05899 
05900   cur = candList->head;
05901   while (cur) {
05902     num++;
05903     next = cur->next;
05904     if (next) {
05905       if (next->prev != cur) {
05906         error++;
05907         if (next->prev) {
05908           fprintf(vis_stderr, "Error : prev of %d is not %d (!= %d) in list\n",
05909                  next->index, cur->index, next->prev->index);
05910         } else {
05911           fprintf(vis_stderr, "Error : prev of %d is not %d (!= nil) in list\n",
05912                  next->index, cur->index);
05913         }
05914       }
05915       if (method == 1) {
05916       } else if (method == 2) {
05917       } else if (method == 3) {
05918         if (info[cur->index].lNum > info[next->index].lNum) {
05919           error++;
05920           fprintf(vis_stderr,
05921                   "Error : cur(%d) lNum(%d) > next(%d) lNum(%d) in row list\n",
05922                   cur->index, info[cur->index].lNum,
05923                   next->index, info[next->index].lNum);
05924         } else if (info[cur->index].lNum == info[next->index].lNum &&
05925                    info[cur->index].gNum < info[next->index].gNum) {
05926           error++;
05927           fprintf(vis_stderr,
05928                   "Error : cur(%d) gNum(%d) < next(%d) gNum(%d) in row list\n",
05929                   cur->index, info[cur->index].gNum,
05930                   next->index, info[next->index].gNum);
05931         } else if (info[cur->index].lNum == info[next->index].lNum &&
05932                    info[cur->index].gNum == info[next->index].gNum &&
05933                    info[cur->index].pos > info[next->index].pos) {
05934           error++;
05935           fprintf(vis_stderr,
05936                   "Error : cur(%d) pos(%d) > next(%d) pos(%d) in row list\n",
05937                   cur->index, info[cur->index].pos,
05938                   next->index, info[next->index].pos);
05939         }
05940       } else if (method == 4) {
05941         if (cur->otherIndex < next->otherIndex) {
05942           error++;
05943           fprintf(vis_stderr, 
05944               "Error : cur(%d) length(%d) < next(%d) length(%d) in col list\n",
05945                   cur->index, cur->otherIndex, next->index, next->otherIndex);
05946         } else if (cur->otherIndex == next->otherIndex &&
05947                    info[cur->index].lNum < info[next->index].lNum) {
05948           error++;
05949           fprintf(vis_stderr,
05950                   "Error : cur(%d) lNum(%d) < next(%d) lNum(%d) in col list\n",
05951                   cur->index, info[cur->index].lNum,
05952                   next->index, info[next->index].lNum);
05953         } else if (cur->otherIndex == next->otherIndex &&
05954                    info[cur->index].lNum == info[next->index].lNum &&
05955                    info[cur->index].pos > info[next->index].pos) {
05956           error++;
05957           fprintf(vis_stderr,
05958                   "Error : cur(%d) pos(%d) > next(%d) pos(%d) in col list\n",
05959                   cur->index, info[cur->index].pos,
05960                   next->index, info[next->index].pos);
05961         }
05962       }
05963     } else {
05964       if (cur != candList->tail) {
05965         error++;
05966         if (candList->tail) {
05967           fprintf(vis_stderr, "Error : different tail in list (%d != %d)\n",
05968                  cur->index, candList->tail->index);
05969         } else {
05970           fprintf(vis_stderr, "Error : different tail in list (%d != nil)\n",
05971                 cur->index);
05972         }
05973       }
05974     }
05975     if (!st_lookup(candList->table, (char *)(long)cur->index, &candidate)) {
05976       error++;
05977       fprintf(vis_stderr, "Error : index %d not in table\n", cur->index);
05978     }
05979     cur = next;
05980   }
05981   if (num != candList->num) {
05982     error++;
05983     fprintf(vis_stderr,
05984             "Error : different number of elements in list (%d != %d)\n",
05985             num, candList->num);
05986   }
05987   if (num != st_count(candList->table)) {
05988     error++;
05989     fprintf(vis_stderr,
05990             "Error : different number of elements in table (%d != %d)\n",
05991             num, st_count(candList->table));
05992   }
05993   assert(!error);
05994 }
05995 
05996 
06006 static void
06007 MlpCluster(mdd_manager *mddManager, char **xy, int nRows, int nCols,
06008                 int nActiveRows, int nActiveCols,
06009                 int *nClusterRows, int *nClusterCols,
06010                 int *rowOrder, int *colOrder,
06011                 RcInfo_t *rowInfo, RcInfo_t *colInfo,
06012                 array_t *clusterArray, array_t *arraySmoothVarBddArray,
06013                 Img_DirectionType direction, int *cRowOrder,
06014                 array_t *nsVarBddArray, int *sccBorder,
06015                 int *varPos, ImgTrmOption_t *option)
06016 {
06017   int                   i, j, row, col;
06018   int                   ncRows, ncCols;
06019   int                   index, qVarPos;
06020   int                   s1, t1, s2;
06021   array_t               *smoothVarBddArray;
06022   mdd_t                 *nsVar, *relation, *cluster, *tempCluster;
06023   ClusterList_t         *list, *headCluster, *tailCluster, *nextList, *prevList;
06024   ClusterSortedList_t   *clusterSortedList;
06025   long                  initialTime, finalTime;
06026   int                   moveFlag = 1;
06027   array_t               *nonAppearingVarBddArray;
06028   char                  *existFlag;
06029   array_t               *supportArray, *tmpArray;
06030   int                   nVars = bdd_num_vars(mddManager);
06031   mdd_t                 *one;
06032 
06033   if (option->mlpVerbosity)
06034     initialTime = util_cpu_time();
06035   else
06036     initialTime = 0;
06037 
06038   ncCols = nActiveCols;
06039   headCluster = NIL(ClusterList_t);
06040   tailCluster = NIL(ClusterList_t);
06041   clusterSortedList = NIL(ClusterSortedList_t);
06042   if (option->mlpCluster == 0) {
06043     if (direction == Img_Forward_c) {
06044       for (i = nActiveRows - 1; i >= 0;) {
06045         row = rowOrder[i];
06046 
06047         list = ALLOC(ClusterList_t, 1);
06048         memset(list, 0, sizeof(ClusterList_t));
06049         list->flag = 3;
06050         list->start = i;
06051         list->end = i;
06052         list->supports = ALLOC(char, nCols);
06053         memcpy(list->supports, xy[row], sizeof(char) * nCols);
06054         list->minCol = rowInfo[row].gMin;
06055         list->maxCol = rowInfo[row].gMax;
06056         list->nSupports = MlpCountSupport(list, colOrder, ncCols);
06057         list->product = bdd_dup(rowInfo[row].data.row.func);
06058         list->nQuantifyVars = 0;
06059         list->affinity = 0.0;
06060         if (rowInfo[row].data.row.nsVarBddArray)
06061           list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
06062         else
06063           list->nsVarBddArray = NIL(array_t);
06064 
06065         if (headCluster)
06066           tailCluster->next = list;
06067         else
06068           headCluster = list;
06069         list->next = NIL(ClusterList_t);
06070         list->prev = tailCluster;
06071         tailCluster = list;
06072 
06073         i--;
06074 
06075         if (sccBorder && sccBorder[i + 1] == 1)
06076           continue;
06077         if (bdd_size(list->product) >= option->clusterSize)
06078           continue;
06079 
06080         while (i >= 0) {
06081           row = rowOrder[i];
06082           relation = rowInfo[row].data.row.func;
06083           if (bdd_size(list->product) >= option->clusterSize)
06084             break;
06085           cluster = bdd_and(list->product, relation, 1, 1);
06086           if (bdd_size(cluster) <= option->clusterSize) {
06087             mdd_free(list->product);
06088             list->product = cluster;
06089             list->start = i;
06090 
06091             if (list->nsVarBddArray) {
06092               array_append(list->nsVarBddArray,
06093                 rowInfo[row].data.row.nsVarBddArray);
06094             }
06095 
06096             list->nSupports = 0;
06097             list->minCol = nActiveCols;
06098             list->maxCol = -1;
06099             s1 = nActiveCols;
06100             t1 = -1;
06101             supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
06102             for (j = 0; j < array_n(supportArray); j++) {
06103               index = array_fetch(int, supportArray, j);
06104               if (varPos[index] == 0) {
06105                 if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
06106                   continue;
06107               }
06108               index = varPos[index];
06109               list->supports[index] = 1;
06110               list->nSupports++;
06111               s2 = colInfo[index].pos;
06112               if (s2 < s1) {
06113                 s1 = s2;
06114                 list->minCol = index;
06115               }
06116               if (s2 > t1) {
06117                 t1 = s2;
06118                 list->maxCol = index;
06119               }
06120             }
06121             array_free(supportArray);
06122 
06123             i--;
06124             if (option->mlpDebug)
06125               CheckCluster(headCluster, ncCols, colInfo, colOrder);
06126           } else {
06127             mdd_free(cluster);
06128             break;
06129           }
06130         }
06131 
06132         ncCols = RemoveLocalVarsInCluster(mddManager, xy,
06133                                             list, nActiveRows, ncCols,
06134                                             rowInfo, colInfo,
06135                                             rowOrder, colOrder,
06136                                             moveFlag, option);
06137       }
06138     } else {
06139       for (i = 0; i < nActiveRows;) {
06140         row = rowOrder[i];
06141 
06142         list = ALLOC(ClusterList_t, 1);
06143         memset(list, 0, sizeof(ClusterList_t));
06144         list->flag = 3;
06145         list->start = i;
06146         list->end = i;
06147         list->supports = ALLOC(char, nCols);
06148         memcpy(list->supports, xy[row], sizeof(char) * nCols);
06149         list->minCol = rowInfo[row].gMin;
06150         list->maxCol = rowInfo[row].gMax;
06151         list->nSupports = MlpCountSupport(list, colOrder, ncCols);
06152         list->product = bdd_dup(rowInfo[row].data.row.func);
06153         list->nQuantifyVars = 0;
06154         list->affinity = 0.0;
06155         if (rowInfo[row].data.row.nsVarBddArray)
06156           list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
06157         else
06158           list->nsVarBddArray = NIL(array_t);
06159 
06160         if (headCluster)
06161           tailCluster->next = list;
06162         else
06163           headCluster = list;
06164         list->next = NIL(ClusterList_t);
06165         list->prev = tailCluster;
06166         tailCluster = list;
06167 
06168         i++;
06169 
06170         if (sccBorder && sccBorder[i - 1] == 2)
06171           continue;
06172         if (bdd_size(list->product) >= option->clusterSize)
06173           continue;
06174 
06175         while (i < nActiveRows) {
06176           row = rowOrder[i];
06177           relation = rowInfo[row].data.row.func;
06178           if (bdd_size(list->product) >= option->clusterSize)
06179             break;
06180           cluster = bdd_and(list->product, relation, 1, 1);
06181           if (bdd_size(cluster) <= option->clusterSize) {
06182             mdd_free(list->product);
06183             list->product = cluster;
06184             list->end = i;
06185 
06186             if (list->nsVarBddArray) {
06187               array_append(list->nsVarBddArray,
06188                 rowInfo[row].data.row.nsVarBddArray);
06189             }
06190 
06191             list->nSupports = 0;
06192             list->minCol = nActiveCols;
06193             list->maxCol = -1;
06194             s1 = nActiveCols;
06195             t1 = -1;
06196             supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
06197             for (j = 0; j < array_n(supportArray); j++) {
06198               index = array_fetch(int, supportArray, j);
06199               if (varPos[index] == 0) {
06200                 if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
06201                   continue;
06202               }
06203               index = varPos[index];
06204               list->supports[index] = 1;
06205               list->nSupports++;
06206               s2 = colInfo[index].pos;
06207               if (s2 < s1) {
06208                 s1 = s2;
06209                 list->minCol = index;
06210               }
06211               if (s2 > t1) {
06212                 t1 = s2;
06213                 list->maxCol = index;
06214               }
06215             }
06216             array_free(supportArray);
06217 
06218             i++;
06219             if (option->mlpDebug)
06220               CheckCluster(headCluster, ncCols, colInfo, colOrder);
06221           } else {
06222             mdd_free(cluster);
06223             break;
06224           }
06225         }
06226 
06227         ncCols = RemoveLocalVarsInCluster(mddManager, xy,
06228                                             list, nActiveRows, ncCols,
06229                                             rowInfo, colInfo,
06230                                             rowOrder, colOrder,
06231                                             moveFlag, option);
06232       }
06233     }
06234   } else { /* option->mlpCluster == 1 */
06235     if (direction == Img_Forward_c) {
06236       for (i = 0; i < nActiveRows; i++) {
06237         row = rowOrder[i];
06238         list = ALLOC(ClusterList_t, 1);
06239         memset(list, 0, sizeof(ClusterList_t));
06240 
06241         if (headCluster && headCluster->flag != 3)
06242           list->flag = 1;
06243         else
06244           list->flag = 2;
06245         list->start = i;
06246         list->end = i;
06247         list->supports = ALLOC(char, nCols);
06248         memcpy(list->supports, xy[row], sizeof(char) * nCols);
06249         list->minCol = rowInfo[row].gMin;
06250         list->maxCol = rowInfo[row].gMax;
06251         list->nSupports = MlpCountSupport(list, colOrder, ncCols);
06252         list->product = bdd_dup(rowInfo[row].data.row.func);
06253         list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
06254                                                  colOrder, ncCols);
06255         if (rowInfo[row].data.row.nsVarBddArray)
06256           list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
06257         else
06258           list->nsVarBddArray = NIL(array_t);
06259 
06260         if (bdd_size(list->product) >= option->clusterSize) {
06261           if (headCluster) {
06262             ncCols = RecursiveCluster(mddManager, headCluster,
06263                                         clusterSortedList,
06264                                         xy, rowInfo, colInfo,
06265                                         rowOrder, colOrder, nActiveRows, ncCols,
06266                                         direction, varPos, moveFlag, option);
06267             if (option->mlpDebug)
06268               CheckCluster(headCluster, ncCols, colInfo, colOrder);
06269           }
06270           list->flag = 3;
06271           ncCols = RemoveLocalVarsInCluster(mddManager, xy,
06272                                             list, nActiveRows, ncCols,
06273                                             rowInfo, colInfo,
06274                                             rowOrder, colOrder,
06275                                             moveFlag, option);
06276           if (option->mlpDebug)
06277             CheckCluster(headCluster, ncCols, colInfo, colOrder);
06278           list->affinity = 0.0;
06279           clusterSortedList = NIL(ClusterSortedList_t);
06280         } else if (sccBorder && i > 0 && sccBorder[i] == 1) {
06281           ncCols = RecursiveCluster(mddManager, headCluster,
06282                                         clusterSortedList,
06283                                         xy, rowInfo, colInfo,
06284                                         rowOrder, colOrder, nActiveRows, ncCols,
06285                                         direction, varPos, moveFlag, option);
06286           if (option->mlpDebug)
06287             CheckCluster(headCluster, ncCols, colInfo, colOrder);
06288           list->flag = 2;
06289           list->affinity = 0.0;
06290           clusterSortedList = NIL(ClusterSortedList_t);
06291           if (option->mlpClusterSortedList) {
06292             clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
06293                                                 option->mlpClusterQuantifyVars);
06294           }
06295         } else {
06296           if (headCluster && headCluster->flag != 3) {
06297             list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
06298                                                 colOrder, ncCols,
06299                                                 option->mlpCluster);
06300           } else
06301             list->affinity = 0.0;
06302           if (option->mlpClusterSortedList) {
06303             clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
06304                                                 option->mlpClusterQuantifyVars);
06305           }
06306         }
06307 
06308         list->next = headCluster;
06309         list->prev = NIL(ClusterList_t);
06310         if (headCluster) {
06311           if (headCluster->flag == 1)
06312             headCluster->flag = 0;
06313           headCluster->prev = list;
06314         }
06315         headCluster = list;
06316       }
06317     } else {
06318       for (i = nActiveRows - 1; i >= 0; i--) {
06319         row = rowOrder[i];
06320         list = ALLOC(ClusterList_t, 1);
06321         memset(list, 0, sizeof(ClusterList_t));
06322 
06323         if (headCluster && headCluster->flag != 3)
06324           list->flag = 1;
06325         else
06326           list->flag = 2;
06327         list->start = i;
06328         list->end = i;
06329         list->supports = ALLOC(char, nCols);
06330         memcpy(list->supports, xy[row], sizeof(char) * nCols);
06331         list->minCol = rowInfo[row].gMin;
06332         list->maxCol = rowInfo[row].gMax;
06333         list->nSupports = MlpCountSupport(list, colOrder, ncCols);
06334         list->product = bdd_dup(rowInfo[row].data.row.func);
06335         list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
06336                                                  colOrder, ncCols);
06337         if (rowInfo[row].data.row.nsVarBddArray)
06338           list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
06339         else
06340           list->nsVarBddArray = NIL(array_t);
06341 
06342         if ( bdd_size(list->product) >= option->clusterSize) {
06343           if (headCluster) {
06344             ncCols = RecursiveCluster(mddManager, headCluster,
06345                                         clusterSortedList,
06346                                         xy, rowInfo, colInfo,
06347                                         rowOrder, colOrder, nActiveRows, ncCols,
06348                                         direction, varPos, moveFlag, option);
06349             if (option->mlpDebug)
06350               CheckCluster(headCluster, ncCols, colInfo, colOrder);
06351           }
06352           list->flag = 3;
06353           ncCols = RemoveLocalVarsInCluster(mddManager, xy,
06354                                             list, nActiveRows, ncCols,
06355                                             rowInfo, colInfo,
06356                                             rowOrder, colOrder,
06357                                             moveFlag, option);
06358           if (option->mlpDebug)
06359             CheckCluster(headCluster, ncCols, colInfo, colOrder);
06360           list->affinity = 0.0;
06361           clusterSortedList = NIL(ClusterSortedList_t);
06362         } else if (sccBorder && i < (nActiveRows - 1) && sccBorder[i] == 2) {
06363           ncCols = RecursiveCluster(mddManager, headCluster,
06364                                         clusterSortedList,
06365                                         xy, rowInfo, colInfo,
06366                                         rowOrder, colOrder, nActiveRows, ncCols,
06367                                         direction, varPos, moveFlag, option);
06368           if (option->mlpDebug)
06369             CheckCluster(headCluster, ncCols, colInfo, colOrder);
06370           list->flag = 2;
06371           list->affinity = 0.0;
06372           clusterSortedList = NIL(ClusterSortedList_t);
06373           if (option->mlpClusterSortedList) {
06374             clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
06375                                                 option->mlpClusterQuantifyVars);
06376           }
06377         } else {
06378           if (headCluster && headCluster->flag != 3) {
06379             list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
06380                                                 colOrder, ncCols,
06381                                                 option->mlpCluster);
06382           } else
06383             list->affinity = 0.0;
06384           if (option->mlpClusterSortedList) {
06385             clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
06386                                                 option->mlpClusterQuantifyVars);
06387           }
06388         }
06389 
06390         list->next = headCluster;
06391         list->prev = NIL(ClusterList_t);
06392         if (headCluster) {
06393           if (headCluster->flag == 1)
06394             headCluster->flag = 0;
06395           headCluster->prev = list;
06396         }
06397         headCluster = list;
06398 
06399         if (option->mlpClusterSortedList && option->mlpDebug) {
06400           int   n1, n2;
06401 
06402           n1 = CountClusterList(headCluster);
06403           n2 = CountClusterSortedList(clusterSortedList);
06404           assert(n1 == n2);
06405         }
06406       }
06407     }
06408 
06409     if (headCluster->flag == 1) {
06410       ncCols = RecursiveCluster(mddManager, headCluster, clusterSortedList,
06411                                 xy, rowInfo, colInfo,
06412                                 rowOrder, colOrder, nActiveRows, ncCols,
06413                                 direction, varPos, moveFlag, option);
06414       if (option->mlpDebug)
06415         CheckCluster(headCluster, ncCols, colInfo, colOrder);
06416     }
06417   }
06418 
06419   list = headCluster;
06420   one = bdd_one(mddManager);
06421   while (list) {
06422     if (bdd_equal(list->product, one)) {
06423       assert(list->nSupports == 0);
06424 
06425       prevList = list->prev;
06426       nextList = list->next;
06427       if ((!prevList) && (!nextList)) /* unity relation */
06428         break;
06429 
06430       mdd_free(list->product);
06431       if (list->nsVarBddArray)
06432         array_free(list->nsVarBddArray);
06433       FREE(list->supports);
06434 
06435       if (nextList) {
06436         if (list->start < nextList->start)
06437           nextList->start = list->start;
06438         if (list->end > nextList->end)
06439           nextList->end = list->end;
06440 
06441         if (list == headCluster)
06442           headCluster = nextList;
06443 
06444         FREE(list);
06445       } else {
06446         if (list->start < prevList->start)
06447           prevList->start = list->start;
06448         if (list->end > prevList->end)
06449           prevList->end = list->end;
06450         FREE(list);
06451       }
06452       if (prevList)
06453         prevList->next = nextList;
06454       if (nextList)
06455         nextList->prev = prevList;
06456       list = nextList;
06457       continue;
06458     }
06459     list = list->next;
06460   }
06461   bdd_free(one);
06462 
06463   if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
06464     PrintMatrixWithCluster(xy, headCluster, ncCols, rowOrder, colOrder,
06465                            direction);
06466     fprintf(vis_stdout, "******** cluster matrix ************\n");
06467     PrintClusterMatrix(headCluster, ncCols, colOrder, direction);
06468   }
06469   if (option->mlpDebug)
06470     CheckCluster(headCluster, ncCols, colInfo, colOrder);
06471 
06472   ncRows = 0;
06473   nonAppearingVarBddArray = NIL(array_t);
06474   if ((direction == Img_Forward_c && option->mlpReorder) ||
06475       (direction == Img_Backward_c && option->mlpPreReorder) ||
06476       option->mlpPostProcess >= 2) {
06477     list = headCluster;
06478     while (list) {
06479       row = rowOrder[ncRows];
06480 
06481       mdd_free(rowInfo[row].data.row.func);
06482       rowInfo[row].data.row.func = list->product;
06483       list->product = NIL(mdd_t);
06484 
06485       if (xy[row])
06486         FREE(xy[row]);
06487       xy[row] = list->supports;
06488       list->supports = NIL(char);
06489 
06490       rowInfo[row].gNum = list->nSupports;
06491       rowInfo[row].gMin = list->minCol;
06492       rowInfo[row].gMax = list->maxCol;
06493       rowInfo[row].lNum = list->nSupports;
06494       rowInfo[row].lMin = list->minCol;
06495       rowInfo[row].lMax = list->maxCol;
06496       rowInfo[row].prevG = -1;
06497       rowInfo[row].nextG = ncCols;
06498 
06499       if (list->nsVarBddArray) {
06500         if (rowInfo[row].data.row.nsVarBddArray)
06501           array_free(rowInfo[row].data.row.nsVarBddArray);
06502         rowInfo[row].data.row.nsVarBddArray = list->nsVarBddArray;
06503         list->nsVarBddArray = NIL(array_t);
06504       }
06505 
06506       nextList = list->next;
06507       FREE(list);
06508       ncRows++;
06509       list = nextList;
06510     }
06511 
06512     if (direction == Img_Forward_c) {
06513       for (i = 0; i < ncRows; i++) {
06514         cRowOrder[i] = rowOrder[ncRows - i - 1];
06515         rowInfo[rowOrder[ncRows - i - 1]].pos = i;
06516       }
06517     } else {
06518       for (i = 0; i < ncRows; i++) {
06519         cRowOrder[i] = rowOrder[i];
06520         rowInfo[rowOrder[i]].pos = i;
06521       }
06522     }
06523 
06524     for (j = 0; j < ncCols; j++) {
06525       col = colOrder[j];
06526       colInfo[col].gNum = 0;
06527       colInfo[col].gMin = ncRows;
06528       colInfo[col].gMax = -1;
06529       for (i = 0; i < ncRows; i++) {
06530         row = cRowOrder[i];
06531         if (xy[row][col]) {
06532           colInfo[col].gNum++;
06533           if (colInfo[col].gMin == ncRows)
06534             colInfo[col].gMin = row;
06535           colInfo[col].gMax = row;
06536         }
06537       }
06538       colInfo[col].lNum = colInfo[col].gNum;
06539       colInfo[col].lMin = colInfo[col].gMin;
06540       colInfo[col].lMax = colInfo[col].gMax;
06541       colInfo[col].prevG = -1;
06542       colInfo[col].nextG = ncRows;
06543     }
06544   } else {
06545     if (direction == Img_Forward_c) {
06546       if (arraySmoothVarBddArray) {
06547         nonAppearingVarBddArray = array_fetch(array_t *,
06548                                               arraySmoothVarBddArray, 0);
06549         if (nCols > ncCols) {
06550           existFlag = ALLOC(char, nVars);
06551           memset(existFlag, 0, sizeof(char) * nVars);
06552 
06553           for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
06554             nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
06555             index = (int)bdd_top_var_id(nsVar);
06556             existFlag[index] = 1;
06557           }
06558 
06559           for (i = ncCols; i < nCols; i++) {
06560             col = colOrder[i];
06561             index = (int)bdd_top_var_id(colInfo[col].data.col.var);
06562             if (!existFlag[index]) {
06563               array_insert_last(bdd_t *, nonAppearingVarBddArray,
06564                                 bdd_dup(colInfo[col].data.col.var));
06565             }
06566           }
06567 
06568           FREE(existFlag);
06569         }
06570         qVarPos = ncCols - 1;
06571         if (qVarPos >= 0) {
06572           col = colOrder[qVarPos];
06573           while (colInfo[col].gNum == 0) {
06574             array_insert_last(bdd_t *, nonAppearingVarBddArray,
06575                                 bdd_dup(colInfo[col].data.col.var));
06576             if (qVarPos == 0)
06577               break;
06578             qVarPos--;
06579             col = colOrder[qVarPos];
06580           }
06581         }
06582       } else
06583         qVarPos = 0; /* to avoid warning */
06584     } else {
06585       if (arraySmoothVarBddArray) {
06586         nonAppearingVarBddArray = array_fetch(array_t *,
06587                                                 arraySmoothVarBddArray, 0);
06588         if (nCols > ncCols) {
06589           for (i = ncCols; i < nCols; i++) {
06590             col = colOrder[i];
06591             if (colInfo[col].data.col.type == 2) {
06592               array_insert_last(bdd_t *, nonAppearingVarBddArray,
06593                                 bdd_dup(colInfo[col].data.col.var));
06594             }
06595           }
06596         }
06597         qVarPos = ncCols - 1;
06598         if (qVarPos >= 0) {
06599           col = colOrder[qVarPos];
06600           while (colInfo[col].gNum == 0) {
06601             if (colInfo[col].data.col.type == 2) {
06602               array_insert_last(bdd_t *, nonAppearingVarBddArray,
06603                                 bdd_dup(colInfo[col].data.col.var));
06604             }
06605             if (qVarPos == 0)
06606               break;
06607             qVarPos--;
06608             col = colOrder[qVarPos];
06609           }
06610         }
06611 
06612         existFlag = ALLOC(char, nVars);
06613         memset(existFlag, 0, sizeof(char) * nVars);
06614 
06615         for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
06616           nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
06617           index = (int)bdd_top_var_id(nsVar);
06618           existFlag[index] = 1;
06619         }
06620 
06621         if (nRows > nActiveRows) {
06622           for (i = nActiveRows; i < nRows; i++) {
06623             row = rowOrder[i];
06624             tmpArray = rowInfo[row].data.row.nsVarBddArray;
06625             for (j = 0; j < array_n(tmpArray); j++) {
06626               nsVar = array_fetch(bdd_t *, tmpArray, j);
06627               index = (int)bdd_top_var_id(nsVar);
06628               existFlag[index] = 1;
06629             }
06630           }
06631         }
06632 
06633         list = headCluster;
06634         while (list) {
06635           supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
06636           for (i = 0; i < array_n(supportArray); i++) {
06637             index = array_fetch(int, supportArray, i);
06638             existFlag[index] = 1;
06639           }
06640           array_free(supportArray);
06641           list = list->next;
06642         }
06643 
06644         list = headCluster;
06645         while (list) {
06646           for (i = 0; i < array_n(list->nsVarBddArray); i++) {
06647             nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
06648             index = (int)bdd_top_var_id(nsVar);
06649             if (!existFlag[index]) {
06650               tmpArray = array_alloc(mdd_t *, 0);
06651               for (j = 0; j < i; j++) {
06652                 nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
06653                 array_insert_last(mdd_t *, tmpArray, nsVar);
06654               }
06655               for (j = i + 1; j < array_n(list->nsVarBddArray); j++) {
06656                 nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
06657                 index = (int)bdd_top_var_id(nsVar);
06658                 if (existFlag[index])
06659                   array_insert_last(mdd_t *, tmpArray, nsVar);
06660               }
06661               array_free(list->nsVarBddArray);
06662               list->nsVarBddArray = tmpArray;
06663               break;
06664             }
06665           }
06666           list = list->next;
06667         }
06668 
06669         for (i = 0; i < array_n(nsVarBddArray); i++) {
06670           nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
06671           index = (int)bdd_top_var_id(nsVar);
06672           if (!existFlag[index])
06673             array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
06674         }
06675 
06676         FREE(existFlag);
06677       } else
06678         qVarPos = 0; /* to avoid warning */
06679     }
06680 
06681     if (direction == Img_Backward_c && nRows > nActiveRows) {
06682       cluster = bdd_one(mddManager);
06683       if (arraySmoothVarBddArray)
06684         smoothVarBddArray = array_alloc(array_t *, 0);
06685       else
06686         smoothVarBddArray = NIL(array_t);
06687       for (i = nActiveRows; i < nRows; i++) {
06688         row = rowOrder[i];
06689         relation = rowInfo[row].data.row.func;
06690         if (bdd_is_tautology(relation, 1))
06691           continue;
06692         if (smoothVarBddArray) {
06693           tmpArray = rowInfo[row].data.row.nsVarBddArray;
06694           for (j = 0; j < array_n(tmpArray); j++) {
06695             nsVar = array_fetch(bdd_t *, tmpArray, j);
06696             array_insert_last(mdd_t *, smoothVarBddArray, bdd_dup(nsVar));
06697           }
06698         }
06699         tempCluster = bdd_and(cluster, relation, 1, 1);
06700         bdd_free(cluster);
06701         cluster = tempCluster;
06702       }
06703       if (bdd_is_tautology(cluster, 1)) {
06704         mdd_free(cluster);
06705         if (smoothVarBddArray)
06706           mdd_array_free(smoothVarBddArray);
06707       } else {
06708         array_insert_last(bdd_t *, clusterArray, cluster);
06709         if (arraySmoothVarBddArray) {
06710           array_insert_last(array_t *, arraySmoothVarBddArray,
06711                             smoothVarBddArray);
06712         }
06713         ncRows++;
06714       }
06715     }
06716 
06717     list = headCluster;
06718     while (list) {
06719       array_insert_last(mdd_t *, clusterArray, list->product);
06720       list->product = NIL(mdd_t);
06721 
06722       if (arraySmoothVarBddArray) {
06723         if (direction == Img_Forward_c) {
06724           smoothVarBddArray = array_alloc(array_t *, 0);
06725           if (qVarPos >= 0) {
06726             col = colOrder[qVarPos];
06727             while (rowInfo[colInfo[col].gMin].pos >= list->start &&
06728                    rowInfo[colInfo[col].gMin].pos <= list->end) {
06729               array_insert_last(bdd_t *, smoothVarBddArray,
06730                                 bdd_dup(colInfo[col].data.col.var));
06731               if (qVarPos == 0)
06732                 break;
06733               qVarPos--;
06734               col = colOrder[qVarPos];
06735             }
06736           }
06737           array_insert_last(array_t *, arraySmoothVarBddArray,
06738                             smoothVarBddArray);
06739         } else {
06740           smoothVarBddArray = array_alloc(array_t *, 0);
06741           for (i = 0; i < array_n(list->nsVarBddArray); i++) {
06742             nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
06743             array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
06744           }
06745 
06746           if (list->nSupports > 0) {
06747             s1 = colInfo[list->minCol].pos;
06748             t1 = colInfo[list->maxCol].pos;
06749             for (i = s1; i <= t1; i++) {
06750               col = colOrder[i];
06751               if (colInfo[col].data.col.type == 2) {
06752                 if (rowInfo[colInfo[col].gMax].pos >= list->start &&
06753                     rowInfo[colInfo[col].gMax].pos <= list->end) {
06754                   array_insert_last(bdd_t *, smoothVarBddArray,
06755                                     bdd_dup(colInfo[col].data.col.var));
06756                 }
06757               }
06758             }
06759           }
06760           array_insert_last(array_t *, arraySmoothVarBddArray,
06761                             smoothVarBddArray);
06762         }
06763       }
06764 
06765       nextList = list->next;
06766       if (list->nsVarBddArray)
06767         array_free(list->nsVarBddArray);
06768       FREE(list->supports);
06769       FREE(list);
06770       ncRows++;
06771       list = nextList;
06772     }
06773 
06774     if (direction == Img_Forward_c && nRows > nActiveRows) {
06775       cluster = bdd_one(mddManager);
06776       for (i = nActiveRows; i < nRows; i++) {
06777         row = rowOrder[i];
06778         relation = rowInfo[row].data.row.func;
06779         if (bdd_is_tautology(relation, 1))
06780           continue;
06781         tempCluster = bdd_and(cluster, relation, 1, 1);
06782         bdd_free(cluster);
06783         cluster = tempCluster;
06784       }
06785       if (bdd_is_tautology(cluster, 1))
06786         mdd_free(cluster);
06787       else {
06788         array_insert_last(bdd_t *, clusterArray, cluster);
06789         if (arraySmoothVarBddArray) {
06790           smoothVarBddArray = array_alloc(array_t *, 0);
06791           array_insert_last(array_t *, arraySmoothVarBddArray,
06792                             smoothVarBddArray);
06793         }
06794         ncRows++;
06795       }
06796     }
06797   }
06798 
06799   *nClusterRows = ncRows;
06800   *nClusterCols = ncCols;
06801 
06802   if (option->mlpVerbosity) {
06803     finalTime = util_cpu_time();
06804     fprintf(vis_stdout, "time for clustering = %10g\n",
06805            (double)(finalTime - initialTime) / 1000.0);
06806   }
06807 }
06808 
06809 
06819 static int
06820 MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols)
06821 {
06822   int   i, col;
06823   int   nSupports = 0;
06824 
06825   for (i = 0; i < nActiveCols; i++) {
06826     col = colOrder[i];
06827     if (list->supports[col])
06828       nSupports++;
06829   }
06830   return(nSupports);
06831 }
06832 
06833 
06843 static float
06844 MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList,
06845                 RcInfo_t *colInfo, int *colOrder,
06846                 int nActiveCols, int clusterMethod)
06847 {
06848   ClusterList_t *minList, *maxList;
06849   int           i, col, s, t;
06850   int           nOverlaps = 0;
06851   float         affinity;
06852 
06853   if (curList->nSupports <= nextList->nSupports) {
06854     minList = curList;
06855     maxList = nextList;
06856   } else {
06857     minList = nextList;
06858     maxList = curList;
06859   }
06860 
06861   s = colInfo[minList->minCol].pos;
06862   t = colInfo[minList->maxCol].pos;
06863   for (i = s; i <= t; i++) {
06864     col = colOrder[i];
06865     if (minList->supports[col] && maxList->supports[col])
06866       nOverlaps++;
06867   }
06868 
06869   if (clusterMethod == 1)
06870     affinity = (float)nOverlaps / (float)minList->nSupports;
06871   else {
06872     affinity = (float)nOverlaps /
06873                 (float)(minList->nSupports + maxList->nSupports - nOverlaps);
06874   }
06875   return(affinity);
06876 }
06877 
06878 
06888 static int
06889 RecursiveCluster(mdd_manager *mddManager, ClusterList_t *headCluster,
06890                  ClusterSortedList_t *clusterSortedList,
06891                  char **xy, RcInfo_t *rowInfo, RcInfo_t *colInfo,
06892                  int *rowOrder, int *colOrder,
06893                  int nActiveRows, int nClusterCols,
06894                  Img_DirectionType direction, int *varPos,
06895                  int moveFlag, ImgTrmOption_t *option)
06896 {
06897   ClusterSortedList_t   *sortedList, *nextSortedList, *prevSortedList;
06898   ClusterSortedList_t   *firstSortedList, *secondSortedList, *saveSortedList;
06899   ClusterSortedList_t   *tailSortedList1, *tailSortedList2;
06900   ClusterList_t         *list, *best;
06901   int                   i, n1, n2;
06902   int                   s1, t1, s2;
06903   mdd_t                 *product;
06904   int                   merge, index;
06905   array_t               *supportArray;
06906 
06907   if (headCluster->flag == 3)
06908     return(nClusterCols);
06909 
06910   assert(headCluster);
06911   if (option->mlpClusterSortedList && option->mlpDebug) {
06912     n1 = CountClusterList(headCluster);
06913     n2 = CountClusterSortedList(clusterSortedList);
06914     assert(n1 == n2);
06915   }
06916 
06917   if (headCluster->flag == 2) {
06918     assert(!headCluster->next || headCluster->next->flag == 3);
06919     headCluster->flag = 3;
06920     nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, headCluster,
06921                                             nActiveRows, nClusterCols,
06922                                             rowInfo, colInfo,
06923                                             rowOrder, colOrder,
06924                                             moveFlag, option);
06925     if (clusterSortedList) {
06926       assert(!clusterSortedList->next);
06927       FREE(clusterSortedList);
06928     }
06929     return(nClusterCols);
06930   }
06931 
06932   merge = 0;
06933   best = NIL(ClusterList_t);
06934   if (option->mlpClusterMerge) {
06935     /* NEED */
06936   }
06937 
06938   if (!best) {
06939     if (clusterSortedList)
06940       best = clusterSortedList->list;
06941     else {
06942       best = headCluster;
06943       list = headCluster->next;
06944       while (list) {
06945         if (list->flag == 2)
06946           break;
06947         if (option->mlpClusterQuantifyVars) {
06948           if (list->nQuantifyVars < best->nQuantifyVars ||
06949               (list->nQuantifyVars == best->nQuantifyVars &&
06950                list->affinity > best->affinity)) {
06951             best = list;
06952           }
06953         } else {
06954           if (list->affinity < option->mlpAffinityThreshold) {
06955             list = list->next;
06956             continue;
06957           }
06958           if (list->affinity > best->affinity ||
06959               (list->affinity == best->affinity &&
06960                list->nQuantifyVars < best->nQuantifyVars)) {
06961             best = list;
06962           }
06963         }
06964         list = list->next;
06965       }
06966     }
06967   }
06968   assert(best->next && best->next->flag != 3);
06969 
06970   list = best->next;
06971   product = mdd_and(best->product, list->product, 1, 1);
06972 
06973   if (merge == 0 && bdd_size(product) > option->clusterSize) {
06974     mdd_free(product);
06975 
06976     firstSortedList = NIL(ClusterSortedList_t);
06977     secondSortedList = NIL(ClusterSortedList_t);
06978     if (option->mlpClusterSortedList) {
06979       tailSortedList1 = NIL(ClusterSortedList_t);
06980       tailSortedList2 = NIL(ClusterSortedList_t);
06981       sortedList = clusterSortedList;
06982       while (sortedList) {
06983         nextSortedList = sortedList->next;
06984         if ((best->start > list->start &&
06985              sortedList->list->start >= best->start) ||
06986             (best->start < list->start &&
06987              sortedList->list->start <= best->start)) {
06988           if (tailSortedList1)
06989             tailSortedList1->next = sortedList;
06990           else
06991             firstSortedList = sortedList;
06992           tailSortedList1 = sortedList;
06993         } else {
06994           if (tailSortedList2)
06995             tailSortedList2->next = sortedList;
06996           else
06997             secondSortedList = sortedList;
06998           tailSortedList2 = sortedList;
06999         }
07000         sortedList->next = NIL(ClusterSortedList_t);
07001         sortedList = nextSortedList;
07002       }
07003     }
07004 
07005     if (best == headCluster) {
07006       best->flag = 3;
07007       if (option->mlpClusterSortedList) {
07008         sortedList = firstSortedList;
07009         firstSortedList = firstSortedList->next;
07010         FREE(sortedList);
07011         assert(!firstSortedList);
07012       }
07013       nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
07014                                                 nActiveRows, nClusterCols,
07015                                                 rowInfo, colInfo,
07016                                                 rowOrder, colOrder,
07017                                                 moveFlag, option);
07018     } else {
07019       best->flag = 2;
07020       if (option->mlpClusterSortedList) {
07021         sortedList = firstSortedList;
07022         prevSortedList = NIL(ClusterSortedList_t);
07023         saveSortedList = NIL(ClusterSortedList_t);
07024         while (sortedList) {
07025           nextSortedList = sortedList->next;
07026           if (sortedList->list == best) {
07027             if (nextSortedList) {
07028               if (prevSortedList)
07029                 prevSortedList->next = sortedList->next;
07030               else
07031                 firstSortedList = sortedList->next;
07032             }
07033             saveSortedList = sortedList;
07034             sortedList->next = NIL(ClusterSortedList_t);
07035             sortedList = nextSortedList;
07036             continue;
07037           }
07038           prevSortedList = sortedList;
07039           sortedList = nextSortedList;
07040         }
07041         prevSortedList->next = saveSortedList;
07042       }
07043       nClusterCols = RecursiveCluster(mddManager, headCluster, firstSortedList,
07044                                         xy, rowInfo, colInfo,
07045                                         rowOrder, colOrder,
07046                                         nActiveRows, nClusterCols,
07047                                         direction, varPos, moveFlag, option);
07048     }
07049     if (option->mlpDebug) {
07050       CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
07051       CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
07052                     rowInfo, colInfo, rowOrder, colOrder,
07053                     0, nActiveRows - 1, 0, nClusterCols - 1, 0);
07054     }
07055 
07056     if (list->flag == 0) {
07057       list->flag = 1;
07058       nClusterCols = RecursiveCluster(mddManager, list, secondSortedList,
07059                                         xy, rowInfo, colInfo,
07060                                         rowOrder, colOrder,
07061                                         nActiveRows, nClusterCols,
07062                                         direction, varPos, moveFlag, option);
07063     } else {
07064       list->flag = 3;
07065       sortedList = secondSortedList;
07066       secondSortedList = secondSortedList->next;
07067       FREE(sortedList);
07068       assert(!secondSortedList);
07069       nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, list,
07070                                                 nActiveRows, nClusterCols,
07071                                                 rowInfo, colInfo,
07072                                                 rowOrder, colOrder,
07073                                                 moveFlag, option);
07074     }
07075     if (option->mlpDebug) {
07076       CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
07077       CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
07078                     rowInfo, colInfo, rowOrder, colOrder,
07079                     0, nActiveRows - 1, 0, nClusterCols - 1, 0);
07080     }
07081   } else {
07082     if (merge == 0 && option->mlpClusterSortedList) {
07083       sortedList = clusterSortedList->next;
07084       FREE(clusterSortedList);
07085       clusterSortedList = sortedList;
07086     }
07087 
07088     mdd_free(best->product);
07089     best->product = product;
07090 
07091     if (list->flag == 2) {
07092       if (best->flag == 1)
07093         best->flag = 3;
07094       else
07095         best->flag = 2;
07096     }
07097 
07098     best->nSupports = 0;
07099     best->minCol = nClusterCols;
07100     best->maxCol = -1;
07101     s1 = nClusterCols;
07102     t1 = -1;
07103     supportArray = mdd_get_bdd_support_ids(mddManager, best->product);
07104     for (i = 0; i < array_n(supportArray); i++) {
07105       index = array_fetch(int, supportArray, i);
07106       if (varPos[index] == 0) {
07107         if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
07108           continue;
07109       }
07110       index = varPos[index];
07111       best->supports[index] = 1;
07112       best->nSupports++;
07113       s2 = colInfo[index].pos;
07114       if (s2 < s1) {
07115         s1 = s2;
07116         best->minCol = index;
07117       }
07118       if (s2 > t1) {
07119         t1 = s2;
07120         best->maxCol = index;
07121       }
07122     }
07123     array_free(supportArray);
07124 
07125     if (best->nsVarBddArray)
07126       array_append(best->nsVarBddArray, list->nsVarBddArray);
07127 
07128     if (list->start < best->start)
07129       best->start = list->start;
07130     if (list->end > best->end)
07131       best->end = list->end;
07132 
07133     if (option->mlpClusterSortedList) {
07134       sortedList = clusterSortedList;
07135       prevSortedList = NIL(ClusterSortedList_t);
07136       if (merge == 0) {
07137         while (sortedList) {
07138           nextSortedList = sortedList->next;
07139           if (option->mlpClusterDynamic) {
07140             if (sortedList->list == list || sortedList->list == best->prev) {
07141               if (prevSortedList)
07142                 prevSortedList->next = sortedList->next;
07143               else
07144                 clusterSortedList = sortedList->next;
07145               FREE(sortedList);
07146               sortedList = nextSortedList;
07147               continue;
07148             }
07149           } else {
07150             if (sortedList->list == list) {
07151               best->affinity = list->affinity;
07152               sortedList->list = best;
07153               break;
07154             }
07155           }
07156           prevSortedList = sortedList;
07157           sortedList = nextSortedList;
07158         }
07159       } else {
07160         while (sortedList) {
07161           nextSortedList = sortedList->next;
07162           if (option->mlpClusterDynamic) {
07163             if (sortedList->list == best ||
07164                 sortedList->list == list || sortedList->list == best->prev) {
07165               if (prevSortedList)
07166                 prevSortedList->next = sortedList->next;
07167               else
07168                 clusterSortedList = sortedList->next;
07169               FREE(sortedList);
07170               sortedList = nextSortedList;
07171               continue;
07172             }
07173           } else {
07174             if (sortedList->list == best) {
07175               if (prevSortedList)
07176                 prevSortedList->next = sortedList->next;
07177               else
07178                 clusterSortedList = sortedList->next;
07179               FREE(sortedList);
07180               sortedList = nextSortedList;
07181               continue;
07182             } else if (sortedList->list == list) {
07183               best->affinity = list->affinity;
07184               sortedList->list = best;
07185               break;
07186             }
07187           }
07188           prevSortedList = sortedList;
07189           sortedList = nextSortedList;
07190         }
07191       }
07192     }
07193 
07194     best->next = list->next;
07195     if (list->next)
07196       list->next->prev = best;
07197 
07198     mdd_free(list->product);
07199     if (list->nsVarBddArray)
07200       array_free(list->nsVarBddArray);
07201     FREE(list->supports);
07202     FREE(list);
07203 
07204     if (merge && best->flag != 3) {
07205       nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
07206                                                 nActiveRows, nClusterCols,
07207                                                 rowInfo, colInfo,
07208                                                 rowOrder, colOrder,
07209                                                 moveFlag, option);
07210     }
07211 
07212     if (best->flag == 3) {
07213       nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
07214                                                 nActiveRows, nClusterCols,
07215                                                 rowInfo, colInfo,
07216                                                 rowOrder, colOrder,
07217                                                 moveFlag, option);
07218     } else {
07219       if (option->mlpClusterDynamic) {
07220         if (best->flag == 2)
07221           best->affinity = 0.0;
07222         else {
07223           best->affinity = MlpSupportAffinity(best, best->next, colInfo,
07224                                                 colOrder, nClusterCols,
07225                                                 option->mlpCluster);
07226         }
07227         if (best != headCluster) {
07228           best->prev->affinity = MlpSupportAffinity(best->prev, best, colInfo,
07229                                                     colOrder, nClusterCols,
07230                                                     option->mlpCluster);
07231         }
07232       }
07233       if (option->mlpClusterQuantifyVars == 2) {
07234         best->nQuantifyVars = MlpNumQuantifyVars(best, rowInfo, colInfo,
07235                                                  colOrder, nClusterCols);
07236       }
07237       if (option->mlpClusterSortedList && option->mlpClusterDynamic) {
07238         clusterSortedList = ClusterSortedListInsert(clusterSortedList, best,
07239                                                 option->mlpClusterQuantifyVars);
07240         if (best != headCluster) {
07241           clusterSortedList = ClusterSortedListInsert(clusterSortedList,
07242                                                 best->prev,
07243                                                 option->mlpClusterQuantifyVars);
07244         }
07245       }
07246     }
07247 
07248     if (headCluster->flag == 1) {
07249       if (option->mlpDebug) {
07250         CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
07251         CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
07252                     rowInfo, colInfo, rowOrder, colOrder,
07253                     0, nActiveRows - 1, 0, nClusterCols - 1, 0);
07254       }
07255       nClusterCols = RecursiveCluster(mddManager, headCluster,
07256                                         clusterSortedList,
07257                                         xy, rowInfo, colInfo,
07258                                         rowOrder, colOrder,
07259                                         nActiveRows, nClusterCols,
07260                                         direction, varPos, moveFlag, option);
07261     } else {
07262       if (!option->mlpClusterDynamic) {
07263         assert(!clusterSortedList->next);
07264         FREE(clusterSortedList);
07265       }
07266     }
07267   }
07268 
07269   return(nClusterCols);
07270 }
07271 
07272 
07282 static int
07283 RemoveLocalVarsInCluster(mdd_manager *mddManager, char **xy,
07284                          ClusterList_t *list,
07285                          int nActiveRows, int nClusterCols,
07286                          RcInfo_t *rowInfo, RcInfo_t *colInfo,
07287                          int *rowOrder, int *colOrder,
07288                          int moveFlag, ImgTrmOption_t *option)
07289 {
07290   int           i, j, k, row, col, otherCol;
07291   int           s1, t1, s2, t2, s3, t3;
07292   mdd_t         *product;
07293   array_t       *localVarBddArray = NIL(array_t);
07294 
07295   s1 = colInfo[list->minCol].pos;
07296   t1 = colInfo[list->maxCol].pos;
07297   for (i = t1; i >= s1; i--) {
07298     col = colOrder[i];
07299     if (colInfo[col].data.col.type == 2 &&
07300         rowInfo[colInfo[col].gMin].pos >= list->start &&
07301         rowInfo[colInfo[col].gMax].pos <= list->end) {
07302       if (!localVarBddArray)
07303         localVarBddArray = array_alloc(bdd_t *, 0);
07304       array_insert_last(bdd_t *, localVarBddArray, colInfo[col].data.col.var);
07305 
07306       list->nSupports--;
07307       if (list->nSupports == 0) {
07308         list->minCol = -1;
07309         list->maxCol = -1;
07310       } else if (list->nSupports == 1) {
07311         if (list->minCol == col)
07312           list->minCol = list->maxCol;
07313         else
07314           list->maxCol = list->minCol;
07315       } else if (list->nSupports > 1) {
07316         if (list->minCol == col) {
07317           for (j = i + 1; j <= t1; j++) {
07318             otherCol = colOrder[j];
07319             if (list->supports[otherCol]) {
07320               list->minCol = otherCol;
07321               break;
07322             }
07323           }
07324         } else if (list->maxCol == col) {
07325           for (j = i - 1; j >= s1; j--) {
07326             otherCol = colOrder[j];
07327             if (list->supports[otherCol]) {
07328               list->maxCol = otherCol;
07329               break;
07330             }
07331           }
07332         }
07333       }
07334 
07335       s2 = list->start;
07336       t2 = list->end;
07337       for (j = s2; j <= t2; j++) {
07338         row = rowOrder[j];
07339         if (xy[row][col]) {
07340           rowInfo[row].gNum--;
07341           if (rowInfo[row].gNum > 0) {
07342             s3 = colInfo[rowInfo[row].gMin].pos;
07343             t3 = colInfo[rowInfo[row].gMax].pos;
07344             if (rowInfo[row].gMin == col) {
07345               for (k = i + 1; k <= t3; k++) {
07346                 otherCol = colOrder[k];
07347                 if (xy[row][otherCol]) {
07348                   rowInfo[row].gMin = otherCol;
07349                   break;
07350                 }
07351               }
07352             } else if (rowInfo[row].gMax == col) {
07353               for (k = i - 1; k >= s3; k--) {
07354                 otherCol = colOrder[k];
07355                 if (xy[row][otherCol]) {
07356                   rowInfo[row].gMax = otherCol;
07357                   break;
07358                 }
07359               }
07360             }
07361           }
07362         }
07363       }
07364 
07365       for (j = i; j < nClusterCols - 1; j++) {
07366         colOrder[j] = colOrder[j + 1];
07367         colInfo[colOrder[j]].pos = j;
07368       }
07369       colOrder[nClusterCols - 1] = col;
07370       colInfo[col].pos = nClusterCols - 1;
07371 
07372       nClusterCols--;
07373 
07374       if (option->mlpDebug) {
07375         CheckCluster(list, nClusterCols, colInfo, colOrder);
07376         CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
07377                     rowInfo, colInfo, rowOrder, colOrder,
07378                     0, nActiveRows - 1, 0, nClusterCols - 1, 0);
07379       }
07380     }
07381   }
07382 
07383   if (localVarBddArray) {
07384     product = bdd_smooth(list->product, localVarBddArray);
07385     mdd_free(list->product);
07386     list->product = product;
07387     array_free(localVarBddArray);
07388     UpdateDisapearingPsVarsInCluster(mddManager, xy,
07389                         nActiveRows, nClusterCols,
07390                         rowOrder, colOrder, rowInfo, colInfo,
07391                         list, moveFlag, option);
07392   }
07393 
07394   return(nClusterCols);
07395 }
07396 
07397 
07407 static int
07408 MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo,
07409                    int *colOrder, int nClusterCols)
07410 {
07411   int   i, s, t, col;
07412   int   nQuantifyVars = 0;
07413 
07414   s = colInfo[list->minCol].pos;
07415   t = colInfo[list->maxCol].pos;
07416   for (i = t; i >= s; i--) {
07417     col = colOrder[i];
07418     if (rowInfo[colInfo[col].gMin].pos >= list->start &&
07419         rowInfo[colInfo[col].gMin].pos <= list->end) {
07420       nQuantifyVars++;
07421     } else
07422       break;
07423   }
07424 
07425   return(nQuantifyVars);
07426 }
07427 
07428 
07438 static ClusterSortedList_t *
07439 ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList,
07440                         ClusterList_t *list, int useQuantifyVars)
07441 {
07442   ClusterSortedList_t   *sortedList, *cur, *prev;
07443 
07444   sortedList = ALLOC(ClusterSortedList_t, 1);
07445   sortedList->list = list;
07446 
07447   if (!clusterSortedList) {
07448     sortedList->next = NIL(ClusterSortedList_t);
07449     return(sortedList);
07450   }
07451 
07452   cur = clusterSortedList;
07453   prev = NIL(ClusterSortedList_t);
07454   while (cur) {
07455     if (list->flag == 2) {
07456       prev = cur;
07457       cur = cur->next;
07458       continue;
07459     }
07460     if (useQuantifyVars) {
07461       if (cur->list->flag == 2 ||
07462           list->nQuantifyVars < cur->list->nQuantifyVars ||
07463           (list->nQuantifyVars == cur->list->nQuantifyVars &&
07464            list->affinity >= cur->list->affinity)) {
07465         sortedList->next = cur;
07466         if (cur == clusterSortedList)
07467           clusterSortedList = sortedList;
07468         else
07469           prev->next = sortedList;
07470         break;
07471       }
07472     } else {
07473       if (cur->list->flag == 2 ||
07474           list->affinity > cur->list->affinity ||
07475           (list->affinity == cur->list->affinity &&
07476            list->nQuantifyVars <= cur->list->nQuantifyVars)) {
07477         sortedList->next = cur;
07478         if (cur == clusterSortedList)
07479           clusterSortedList = sortedList;
07480         else
07481           prev->next = sortedList;
07482         break;
07483       }
07484     }
07485     prev = cur;
07486     cur = cur->next;
07487   }
07488   if (!cur) {
07489     prev->next = sortedList;
07490     sortedList->next = NIL(ClusterSortedList_t);
07491   }
07492   return(clusterSortedList);
07493 }
07494 
07495 
07505 static int
07506 CountClusterList(ClusterList_t *clusterList)
07507 {
07508   ClusterList_t *list;
07509   int           n = 0;
07510 
07511   list = clusterList;
07512   while (list) {
07513     if (list->flag == 3)
07514       break;
07515     n++;
07516     if (list->flag == 2)
07517       break;
07518     list = list->next;
07519   }
07520 
07521   return(n);
07522 }
07523 
07524 
07534 static int
07535 CountClusterSortedList(ClusterSortedList_t *clusterSortedList)
07536 {
07537   ClusterSortedList_t   *sortedList;
07538   int                   n = 0;
07539 
07540   sortedList = clusterSortedList;
07541   while (sortedList) {
07542     n++;
07543     sortedList = sortedList->next;
07544   }
07545 
07546   return(n);
07547 }
07548 
07549 
07559 static array_t *
07560 CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray,
07561                      ImgFunctionData_t *functionData, array_t *nsVarBddArray,
07562                      ImgTrmOption_t *option)
07563 {
07564   array_t               *clusteredRelationArray;
07565   array_t               *partitionArray;
07566   Part_Subsystem_t      *partitionSubsystem;
07567   st_table              *vertexTable;
07568   int                   i, j;
07569   int                   mddId;
07570   long                  bddId;
07571   Ntk_Node_t            *latch;
07572   mdd_t                 *cluster, *product, *relation, *var;
07573   char                  *latchName;
07574   st_generator          *stGen;
07575   st_table              *id2relation;
07576   array_t               *bddIdArray;
07577   int                   nVars;
07578   char                  *nsVarFlag;
07579   array_t               *domainVars;
07580 
07581   if (array_n(functionData->domainVars) == array_n(functionData->rangeVars))
07582     domainVars = functionData->domainVars;
07583   else {
07584     domainVars = array_alloc(int, 0);
07585     for (i = 0; i < array_n(functionData->rangeVars); i++) {
07586       mddId = array_fetch(int, functionData->domainVars, i);
07587       array_insert_last(int, domainVars, mddId);
07588     }
07589   }
07590   partitionArray = Fsm_ArdcDecomposeStateSpace(functionData->network,
07591                                                 domainVars,
07592                                                 functionData->roots,
07593                                                 NIL(Fsm_ArdcOptions_t));
07594   if (domainVars != functionData->domainVars)
07595     array_free(domainVars);
07596 
07597   nVars = bdd_num_vars(mddManager);
07598   nsVarFlag = ALLOC(char, nVars);
07599   memset(nsVarFlag, 0, sizeof(char) * nVars);
07600   for (i = 0; i < array_n(nsVarBddArray); i++) {
07601     var = array_fetch(mdd_t *, nsVarBddArray, i);
07602     bddId = (long) bdd_top_var_id(var);
07603     nsVarFlag[bddId] = 1;
07604   }
07605   clusteredRelationArray = array_alloc(mdd_t *, 0);
07606   id2relation = st_init_table(st_numcmp, st_numhash);
07607   for (i = 0; i < array_n(relationArray); i++) {
07608     relation = array_fetch(mdd_t *, relationArray, i);
07609     bddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
07610     for (j = 0; j < array_n(bddIdArray); j++) {
07611       bddId = (long) array_fetch(int, bddIdArray, j);
07612       if (nsVarFlag[bddId]) {
07613         st_insert(id2relation, (char *)bddId, (char *)relation);
07614         break;
07615       }
07616     }
07617 
07618     /* the relation of intermediate variable */
07619     if (j == array_n(bddIdArray)) {
07620       array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
07621     }
07622 
07623     array_free(bddIdArray);
07624   }
07625   FREE(nsVarFlag);
07626 
07627   arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
07628     cluster = mdd_one(mddManager);
07629     vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
07630     st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
07631       latch = Ntk_NetworkFindNodeByName(functionData->network, latchName); 
07632       mddId = Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
07633       bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
07634       for (j = 0; j < array_n(bddIdArray); j++) {
07635         bddId = (long) array_fetch(int, bddIdArray, j);
07636         if (st_lookup(id2relation, (char *)bddId, &relation)) {
07637           st_delete(id2relation, &bddId, NULL);
07638           product = mdd_and(cluster, relation, 1, 1);
07639           mdd_free(cluster);
07640           cluster = product;
07641         }
07642       }
07643       array_free(bddIdArray);
07644     }
07645     Part_PartitionSubsystemFree(partitionSubsystem);
07646     array_insert_last(mdd_t *, clusteredRelationArray, cluster);
07647   }
07648   array_free(partitionArray);
07649 
07650   st_foreach_item(id2relation, stGen, &bddId, &relation) {
07651     array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
07652   }
07653   st_free_table(id2relation);
07654 
07655 /*
07656   if (option->mlpDebug) {
07657     mdd_t       *tr1, *tr2, *tmp;
07658 
07659     tr1 = mdd_one(mddManager);
07660     for (i = 0; i < array_n(relationArray); i++) {
07661       relation = array_fetch(mdd_t *, relationArray, i);
07662       tmp = mdd_and(tr1, relation, 1, 1);
07663       mdd_free(tr1);
07664       tr1 = tmp;
07665     }
07666 
07667     tr2 = mdd_one(mddManager);
07668     for (i = 0; i < array_n(clusteredRelationArray); i++) {
07669       relation = array_fetch(mdd_t *, clusteredRelationArray, i);
07670       tmp = mdd_and(tr2, relation, 1, 1);
07671       mdd_free(tr2);
07672       tr2 = tmp;
07673     }
07674 
07675     assert(mdd_equal(tr1, tr2));
07676     mdd_free(tr1);
07677     mdd_free(tr2);
07678   }
07679 */
07680 
07681   return(clusteredRelationArray);
07682 }
07683 
07684 
07694 static void
07695 SortCol(char **xy, int nRows, int nCols,
07696         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder)
07697 {
07698   int   x, y, i, j, row, col, lastVar;
07699   int   otherRow, otherCol;
07700 
07701   lastVar = nCols - 1;
07702 
07703   for (x = nRows - 1; x >= 0; x--) {
07704     row = rowOrder[x];
07705     for (y = lastVar; y >= 0; y--) {
07706       col = colOrder[y];
07707       if (colInfo[col].gMin == row) {
07708         if (y == lastVar) {
07709           lastVar--;
07710           continue;
07711         }
07712         for (j = y; j < lastVar; j++) {
07713           colOrder[j] = colOrder[j + 1];
07714           colInfo[colOrder[j]].pos = j;
07715         }
07716         colOrder[lastVar] = col;
07717         colInfo[col].pos = lastVar;
07718         for (i = x; i < nRows; i++) {
07719           otherRow = rowOrder[i];
07720           if (colInfo[rowInfo[otherRow].gMax].pos < lastVar)
07721             rowInfo[otherRow].gMax = col;
07722           if (rowInfo[otherRow].gMin == col) {
07723             for (j = 0; j < nCols; j++) {
07724               otherCol = colOrder[j];
07725               if (xy[otherRow][otherCol]) {
07726                 rowInfo[otherRow].gMin = otherCol;
07727                 break;
07728               }
07729             }
07730           }
07731         }
07732         lastVar--;
07733       }
07734     }
07735   }
07736 }
07737 
07738 
07748 static void
07749 UpdateDisapearingPsVars(mdd_manager *mddManager, char **xy,
07750                         int nActiveRows, int nActiveCols,
07751                         int *rowOrder, int *colOrder,
07752                         RcInfo_t *rowInfo, RcInfo_t *colInfo,
07753                         int row, ImgTrmOption_t *option)
07754 {
07755   int           i, id, x, y, s, t, col, tmpRow;
07756   mdd_t         *relation;
07757   array_t       *supportArray;
07758   char          *supportIndex;
07759   int           nVars;
07760 
07761   nVars = bdd_num_vars(mddManager);
07762   relation = rowInfo[row].data.row.func;
07763   supportIndex = ALLOC(char, nVars);
07764   memset(supportIndex, 0, sizeof(char) * nVars);
07765   supportArray = mdd_get_bdd_support_ids(mddManager, relation);
07766   for (i = 0; i < array_n(supportArray); i++) {
07767     id = array_fetch(int, supportArray, i);
07768     supportIndex[id] = 1;
07769   }
07770   array_free(supportArray);
07771 
07772   s = colInfo[rowInfo[row].gMin].pos;
07773   t = colInfo[rowInfo[row].gMax].pos;
07774   x = rowInfo[row].pos;
07775   rowInfo[row].gNum = 0;
07776   rowInfo[row].gMin = nActiveCols;
07777   rowInfo[row].gMax = -1;
07778   for (y = s; y <= t; y++) {
07779     col = colOrder[y];
07780     if (!xy[row][col])
07781       continue;
07782     id = (int)bdd_top_var_id(colInfo[col].data.col.var);
07783     if (supportIndex[id]) {
07784       rowInfo[row].gNum++;
07785       if (rowInfo[row].gMin == nActiveCols)
07786         rowInfo[row].gMin = col;
07787       rowInfo[row].gMax = col;
07788     } else {
07789       xy[row][col] = 0;
07790       if (colInfo[col].gNum == 1) {
07791         colInfo[col].gNum = 0;
07792         colInfo[col].gMin = nActiveRows;
07793         colInfo[col].gMax = -1;
07794       } else if (colInfo[col].gNum == 2) {
07795         colInfo[col].gNum = 1;
07796         if (colInfo[col].gMin == row)
07797           colInfo[col].gMin = colInfo[col].gMax;
07798         else
07799           colInfo[col].gMax = colInfo[col].gMin;
07800       } else {
07801         colInfo[col].gNum--;
07802         if (row == colInfo[col].gMin) {
07803           for (i = x + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
07804             tmpRow = rowOrder[i];
07805             if (xy[tmpRow][col]) {
07806               colInfo[col].gMin = tmpRow;
07807               break;
07808             }
07809           }
07810         } else if (row == colInfo[col].gMax) {
07811           for (i = x - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
07812             tmpRow = rowOrder[i];
07813             if (xy[tmpRow][col]) {
07814               colInfo[col].gMax = tmpRow;
07815               break;
07816             }
07817           }
07818         }
07819       }
07820     }
07821   }
07822 
07823   FREE(supportIndex);
07824 }
07825 
07826 
07836 static void
07837 UpdateDisapearingPsVarsInCluster(mdd_manager *mddManager, char **xy,
07838                         int nActiveRows, int nActiveCols,
07839                         int *rowOrder, int *colOrder,
07840                         RcInfo_t *rowInfo, RcInfo_t *colInfo,
07841                         ClusterList_t *list, int moveFlag,
07842                         ImgTrmOption_t *option)
07843 {
07844   int           i, j, k, y, id, row, col, otherRow, otherCol;
07845   int           s1, t1, s2, t2, s3, t3, t4;
07846   mdd_t         *relation;
07847   array_t       *supportArray;
07848   char          *supportIndex;
07849   int           nVars;
07850   ClusterList_t *otherList;
07851 
07852   if (list->nSupports == 0)
07853     return;
07854 
07855   nVars = bdd_num_vars(mddManager);
07856   relation = list->product;
07857   supportIndex = ALLOC(char, nVars);
07858   memset(supportIndex, 0, sizeof(char) * nVars);
07859   supportArray = mdd_get_bdd_support_ids(mddManager, relation);
07860   for (i = 0; i < array_n(supportArray); i++) {
07861     id = array_fetch(int, supportArray, i);
07862     supportIndex[id] = 1;
07863   }
07864   array_free(supportArray);
07865 
07866   s1 = colInfo[list->minCol].pos;
07867   t1 = colInfo[list->maxCol].pos;
07868   for (y = t1; y >= s1; y--) {
07869     col = colOrder[y];
07870     if (!list->supports[col])
07871       continue;
07872     id = (int)bdd_top_var_id(colInfo[col].data.col.var);
07873     if (!supportIndex[id]) {
07874       list->nSupports--;
07875       list->supports[col] = 0;
07876       if (list->nSupports == 0) {
07877         list->minCol = -1;
07878         list->maxCol = -1;
07879       } else if (list->nSupports == 1) {
07880         if (list->minCol == col)
07881           list->minCol = list->maxCol;
07882         else
07883           list->maxCol = list->minCol;
07884       } else if (list->nSupports > 1) {
07885         if (list->minCol == col) {
07886           for (j = y + 1; j <= t1; j++) {
07887             otherCol = colOrder[j];
07888             if (list->supports[otherCol]) {
07889               list->minCol = otherCol;
07890               break;
07891             }
07892           }
07893         } else if (list->maxCol == col) {
07894           for (j = y - 1; j >= s1; j--) {
07895             otherCol = colOrder[j];
07896             if (list->supports[otherCol]) {
07897               list->maxCol = otherCol;
07898               break;
07899             }
07900           }
07901         }
07902       }
07903 
07904       for (j = list->start; j <= list->end; j++) {
07905         row = rowOrder[j];
07906         if (xy[row][col]) {
07907           xy[row][col] = 0;
07908           colInfo[col].gNum--;
07909           rowInfo[row].gNum--;
07910           if (rowInfo[row].gNum > 0) {
07911             s2 = colInfo[rowInfo[row].gMin].pos;
07912             t2 = colInfo[rowInfo[row].gMax].pos;
07913             if (rowInfo[row].gMin == col) {
07914               for (k = y + 1; k <= t2; k++) {
07915                 otherCol = colOrder[k];
07916                 if (xy[row][otherCol]) {
07917                   rowInfo[row].gMin = otherCol;
07918                   break;
07919                 }
07920               }
07921             } else if (rowInfo[row].gMax == col) {
07922               for (k = y - 1; k >= s2; k--) {
07923                 otherCol = colOrder[k];
07924                 if (xy[row][otherCol]) {
07925                   rowInfo[row].gMax = otherCol;
07926                   break;
07927                 }
07928               }
07929             }
07930           } else {
07931             rowInfo[row].gMin = -1;
07932             rowInfo[row].gMax = nActiveCols;
07933           }
07934         }
07935       }
07936 
07937       if (colInfo[col].gNum == 0) {
07938         colInfo[col].lNum = 0;
07939         colInfo[col].gMin = nActiveRows;
07940         colInfo[col].lMin = nActiveRows;
07941         colInfo[col].gMax = -1;
07942         colInfo[col].lMax = -1;
07943       } else if (colInfo[col].gNum == 1) {
07944         colInfo[col].lNum = 1;
07945         if (rowInfo[colInfo[col].gMax].pos > list->end) {
07946           colInfo[col].gMin = colInfo[col].gMax;
07947           colInfo[col].lMin = colInfo[col].gMax;
07948         } else {
07949           colInfo[col].gMax = colInfo[col].gMin;
07950           colInfo[col].lMax = colInfo[col].gMin;
07951         }
07952       } else {
07953         colInfo[col].lNum = colInfo[col].gNum;
07954         if (rowInfo[colInfo[col].gMin].pos >= list->start &&
07955             rowInfo[colInfo[col].gMin].pos <= list->end) {
07956           for (i = list->end + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
07957             otherRow = rowOrder[i];
07958             if (xy[otherRow][col]) {
07959               colInfo[col].gMin = otherRow;
07960               colInfo[col].lMin = otherRow;
07961               break;
07962             }
07963           }
07964         } else if (rowInfo[colInfo[col].gMax].pos >= list->start &&
07965                    rowInfo[colInfo[col].gMax].pos <= list->end) {
07966           for (i = list->start - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
07967             otherRow = rowOrder[i];
07968             if (xy[otherRow][col]) {
07969               colInfo[col].gMax = otherRow;
07970               colInfo[col].lMax = otherRow;
07971               break;
07972             }
07973           }
07974         }
07975       }
07976 
07977       if (moveFlag) {
07978         if (colInfo[col].gNum == 0) {
07979           if (y < nActiveCols - 1) {
07980             for (j = y; j < nActiveCols - 1; j++) {
07981               colOrder[j] = colOrder[j + 1];
07982               colInfo[colOrder[j]].pos = j;
07983             }
07984             colOrder[nActiveCols - 1] = col;
07985             colInfo[col].pos = nActiveCols - 1;
07986           }
07987         } else if (rowInfo[colInfo[col].gMin].pos > list->end) {
07988           if (list->prev && list->prev->start > list->start) {
07989             /* Image */
07990             otherList = list->prev;
07991             while (!otherList->supports[col])
07992               otherList = otherList->prev;
07993           } else if (list->next && list->next->start > list->start) {
07994             /* Preimage */
07995             otherList = list->next;
07996             while (!otherList->supports[col])
07997               otherList = otherList->next;
07998           } else
07999             otherList = NIL(ClusterList_t);
08000 
08001           if (otherList) {
08002             t2 = colInfo[otherList->maxCol].pos;
08003             if (y != t2) {
08004               for (j = y; j < t2; j++) {
08005                 colOrder[j] = colOrder[j + 1];
08006                 colInfo[colOrder[j]].pos = j;
08007               }
08008               colOrder[t2] = col;
08009               colInfo[col].pos = t2;
08010               otherList->maxCol = col;
08011               if (otherList->minCol == col) {
08012                 for (j = y; j < t2; j++) {
08013                   otherCol = colOrder[j];
08014                   if (otherList->supports[otherCol]) {
08015                     otherList->minCol = otherCol;
08016                     break;
08017                   }
08018                 }
08019               }
08020 
08021               s3 = rowInfo[colInfo[col].gMin].pos;
08022               t3 = rowInfo[colInfo[col].gMax].pos;
08023               for (j = s3; j <= t3; j++) {
08024                 otherRow = rowOrder[j];
08025                 if (xy[otherRow][col]) {
08026                   if (rowInfo[otherRow].gNum > 1) {
08027                     t4 = colInfo[rowInfo[otherRow].gMax].pos;
08028                     if (t4 <= t2)
08029                       rowInfo[otherRow].gMax = col;
08030                     if (rowInfo[otherRow].gMin == col) {
08031                       for (k = y; k <= t4; k++) {
08032                         otherCol = colOrder[k];
08033                         if (xy[otherRow][otherCol]) {
08034                           rowInfo[otherRow].gMin = col;
08035                           break;
08036                         }
08037                       }
08038                     }
08039                   }
08040                 }
08041               }
08042             }
08043           }
08044         }
08045       }
08046 
08047       if (option->mlpDebug) {
08048         CheckCluster(list, nActiveCols, colInfo, colOrder);
08049         CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
08050                     rowInfo, colInfo, rowOrder, colOrder,
08051                     0, nActiveRows - 1, 0, nActiveCols - 1, 0);
08052       }
08053     }
08054   }
08055 
08056   FREE(supportIndex);
08057 }
08058 
08059 
08069 static void
08070 UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray,
08071                         int nRows, RcInfo_t *rowInfo, int *rowOrder,
08072                         array_t *nonAppearingVarBddArray)
08073 {
08074   int           i, j, k, row, index, nVars;
08075   mdd_t         *nsVar, *relation;
08076   char          *existFlag;
08077   array_t       *supportArray, *tmpArray;
08078 
08079   nVars = bdd_num_vars(mddManager);
08080   existFlag = ALLOC(char, nVars);
08081   memset(existFlag, 0, sizeof(char) * nVars);
08082 
08083   for (i = 0; i < nRows; i++) {
08084     row = rowOrder[i];
08085     relation = rowInfo[row].data.row.func;
08086     supportArray = mdd_get_bdd_support_ids(mddManager, relation);
08087     for (j = 0; j < array_n(supportArray); j++) {
08088       index = array_fetch(int, supportArray, j);
08089       existFlag[index] = 1;
08090     }
08091     array_free(supportArray);
08092   }
08093 
08094   for (i = 0; i < nRows; i++) {
08095     row = rowOrder[i];
08096     for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
08097       nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
08098       index = (int)bdd_top_var_id(nsVar);
08099       if (!existFlag[index]) {
08100         tmpArray = array_alloc(mdd_t *, 0);
08101         for (k = 0; k < j; k++) {
08102           nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
08103           array_insert_last(mdd_t *, tmpArray, nsVar);
08104         }
08105         for (k = j + 1; k < array_n(rowInfo[row].data.row.nsVarBddArray); k++) {
08106           nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
08107           index = (int)bdd_top_var_id(nsVar);
08108           if (existFlag[index])
08109             array_insert_last(mdd_t *, tmpArray, nsVar);
08110         }
08111         array_free(rowInfo[row].data.row.nsVarBddArray);
08112         rowInfo[row].data.row.nsVarBddArray = tmpArray;
08113         break;
08114       }
08115     }
08116   }
08117 
08118   for (i = 0; i < array_n(nsVarBddArray); i++) {
08119     nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
08120     index = (int)bdd_top_var_id(nsVar);
08121     if (!existFlag[index])
08122       array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
08123   }
08124 
08125   FREE(existFlag);
08126 }
08127 
08128 
08138 static void
08139 WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo)
08140 {
08141   int   i, col;
08142   mdd_t *var;
08143   char  *name;
08144 
08145   for (i = 0; i < nCols; i++) {
08146     col = colOrder[i];
08147     var = colInfo[col].data.col.var;
08148     name = mdd_read_var_name(var);
08149     fprintf(fout, "%s\n", name);
08150   }
08151 }