source: vis_dev/vis-2.3/src/img/imgMlp.c @ 31

Last change on this file since 31 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 231.1 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [imgMlp.c]
4
5  PackageName [img]
6
7  Synopsis    [Routines for image computation using MLP(Minimal Lifetime
8  Permutation) published in FMCAD00.]
9
10  Description []
11
12  SeeAlso     []
13
14  Author      [In-Ho Moon]
15
16  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
17  All rights reserved.
18
19  Permission is hereby granted, without written agreement and without license
20  or royalty fees, to use, copy, modify, and distribute this software and its
21  documentation for any purpose, provided that the above copyright notice and
22  the following two paragraphs appear in all copies of this software.
23
24  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
25  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
26  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
27  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
30  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
32  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
33  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
34
35******************************************************************************/
36#include "imgInt.h"
37#include "fsm.h"
38
39static char rcsid[] UNUSED = "$Id: imgMlp.c,v 1.31 2005/04/26 19:08:33 jinh Exp $";
40
41
42/*---------------------------------------------------------------------------*/
43/* Constant declarations                                                     */
44/*---------------------------------------------------------------------------*/
45
46/*---------------------------------------------------------------------------*/
47/* Type declarations                                                         */
48/*---------------------------------------------------------------------------*/
49
50
51/*---------------------------------------------------------------------------*/
52/* Structure declarations                                                    */
53/*---------------------------------------------------------------------------*/
54
55/**Struct**********************************************************************
56
57  Synopsis    [This structure contains the information of each row and
58  column.]
59
60  Description []
61
62******************************************************************************/
63typedef struct RcInfo_s {
64  int   pos;    /* level */
65  int   lNum;
66  int   lMin;   /* index */
67  int   lMax;   /* index */
68  int   gNum;
69  int   gMin;   /* index */
70  int   gMax;   /* index */
71  int   prevG;  /* level */
72  int   nextG;  /* level */
73  union {
74    struct {
75      bdd_t     *func;
76      array_t   *nsVarBddArray;
77    } row;
78    struct {
79      bdd_t     *var;
80      int       type;
81    } col;
82  } data;
83} RcInfo_t;
84
85/**Struct**********************************************************************
86
87  Synopsis    [This structure is a list of row and coulmn.]
88
89  Description []
90
91******************************************************************************/
92typedef struct RcList_s {
93  int                   index;
94  int                   otherIndex;
95  struct RcList_s       *next;
96  struct RcList_s       *prev;
97} RcList_t;
98
99/**Struct**********************************************************************
100
101  Synopsis    [This structure contains the information of row and column
102  list.]
103
104  Description []
105
106******************************************************************************/
107typedef struct RcListInfo_s {
108  int           num;
109  int           maxNum;
110  int           curIndex;
111  st_table      *table;
112  RcList_t      *cur;
113  RcList_t      *head;
114  RcList_t      *tail;
115} RcListInfo_t;
116
117/**Struct**********************************************************************
118
119  Synopsis    [This structure contains the information of each cluster.]
120
121  Description []
122
123******************************************************************************/
124typedef struct ClusterList_s {
125  int                   flag;   /* 0 : to be conjuncted
126                                   1 : start element
127                                   2 : last element
128                                   3 : isolated
129                                */
130  int                   start;
131  int                   end;
132  char                  *supports;
133  int                   minCol; /* index */
134  int                   maxCol; /* index */
135  int                   nSupports;
136  float                 affinity;
137  int                   nQuantifyVars;
138  mdd_t                 *product;
139  array_t               *nsVarBddArray;
140  struct ClusterList_s  *prev;
141  struct ClusterList_s  *next;
142} ClusterList_t;
143
144/**Struct**********************************************************************
145
146  Synopsis    [This structure is a list of a sorted cluster.]
147
148  Description []
149
150******************************************************************************/
151typedef struct ClusterSortedList_s {
152  ClusterList_t                 *list;
153  struct ClusterSortedList_s    *next;
154} ClusterSortedList_t;
155
156/**Struct**********************************************************************
157
158  Synopsis    [This structure contains the information of the list of
159  connected component.]
160
161  Description []
162
163******************************************************************************/
164typedef struct SccList_s {
165  int                   startFunc;
166  int                   lastFunc;
167  int                   startVar;
168  int                   lastVar;
169  int                   nFuncs;
170  int                   nVars;
171  struct SccList_s      *next;
172} SccList_t;
173
174/**Struct**********************************************************************
175
176  Synopsis    [This structure constains latch information from reading a
177  cluster file.]
178
179  Description []
180
181******************************************************************************/
182typedef struct LatchList_s {
183  int           number;
184  int           bddId;
185  mdd_t         *relation;
186  st_table      *table;
187} LatchList_t;
188
189
190/*---------------------------------------------------------------------------*/
191/* Variable declarations                                                     */
192/*---------------------------------------------------------------------------*/
193
194static  int     nMoves;
195
196
197/*---------------------------------------------------------------------------*/
198/* Macro declarations                                                        */
199/*---------------------------------------------------------------------------*/
200
201
202/**AutomaticStart*************************************************************/
203
204/*---------------------------------------------------------------------------*/
205/* Static function prototypes                                                */
206/*---------------------------------------------------------------------------*/
207
208static 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);
209static 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);
210static int SccSortListIncreasingWithVars(const void *p1, const void *p2);
211static int SccSortListDecreasingWithVars(const void *p1, const void *p2);
212static int SccSortListIncreasingWithArea(const void *p1, const void *p2);
213static int SccSortListDecreasingWithArea(const void *p1, const void *p2);
214static int SccSortListIncreasingWithRatio(const void *p1, const void *p2);
215static int SccSortListDecreasingWithRatio(const void *p1, const void *p2);
216static int SccSortRc(const void *p1, const void *p2);
217static void FreeSccList(SccList_t *sccHeadList);
218static int NumOfSccs(SccList_t *sccHeadList);
219static 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);
220static 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);
221static 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);
222static 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);
223static 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);
224static 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);
225static 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);
226static 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);
227static 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);
228static 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);
229static 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);
230static 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);
231static 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);
232static 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);
233static void PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols, int *rowOrder, int *colOrder, Img_DirectionType direction);
234static void PrintClusterMatrix(ClusterList_t *headCluster, int nCols, int *colOrder, Img_DirectionType direction);
235static 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);
236static void CheckCluster(ClusterList_t *headCluster, int nCols, RcInfo_t *colInfo, int *colOrder);
237static void WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo);
238static void PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
239static void PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
240static RcListInfo_t * SortedListAlloc(void);
241static void SortedListFree(RcListInfo_t *candList);
242static void SortedListInsert(RcListInfo_t *candList, int index, int otherIndex, RcInfo_t *otherInfo, int method);
243static void SortedListDelete(RcListInfo_t *candList, int index);
244static void SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method);
245static void CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method);
246static 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);
247static int MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols);
248static float MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList, RcInfo_t *colInfo, int *colOrder, int nActiveCols, int clusterMethod);
249static 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);
250static 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);
251static int MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *colOrder, int nClusterCols);
252static ClusterSortedList_t * ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList, ClusterList_t *list, int useQuantifyVars);
253static int CountClusterList(ClusterList_t *clusterList);
254static int CountClusterSortedList(ClusterSortedList_t *clusterSortedList);
255static array_t * CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray, ImgFunctionData_t *functionData, array_t *nsVarBddArray, ImgTrmOption_t *option);
256static void SortCol(char **xy, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder);
257static 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);
258static 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);
259static void UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray, int nRows, RcInfo_t *rowInfo, int *rowOrder, array_t *nonAppearingVarBddArray);
260static void WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo);
261
262/**AutomaticEnd***************************************************************/
263
264
265/*---------------------------------------------------------------------------*/
266/* Definition of exported functions                                          */
267/*---------------------------------------------------------------------------*/
268
269
270/**Function********************************************************************
271
272  Synopsis    [Prints the options for MLP image computation.]
273
274  Description [Prints the options for MLP image computation.]
275
276  SideEffects []
277
278  SeeAlso     []
279
280******************************************************************************/
281void
282Img_PrintMlpOptions(void)
283{
284  ImgTrmOption_t        *options;
285  char                  dummy[80];
286
287  options = ImgGetTrmOptions();
288
289  switch (options->mlpCluster) {
290  case 0 :
291    sprintf(dummy, "linear clustering");
292    break;
293  case 1 :
294    sprintf(dummy, "affinity based tree clustering (default)");
295    break;
296  default :
297    sprintf(dummy, "invalid");
298    break;
299  }
300  fprintf(vis_stdout, "MLP: mlp_cluster = %d (%s)\n",
301          options->mlpCluster, dummy);
302
303  switch (options->mlpReorder) {
304  case 0 :
305    sprintf(dummy, "no reordering after clustering (default)");
306    break;
307  case 1 :
308    sprintf(dummy, "reorder using MLP after clustering (inside)");
309    break;
310  case 2 :
311    sprintf(dummy, "reorder using MLP after clustering (outside)");
312    break;
313  case 3 :
314    sprintf(dummy, "reorder using IWLS95 after clustering");
315    break;
316  default :
317    sprintf(dummy, "invalid");
318    break;
319  }
320  fprintf(vis_stdout, "MLP: mlp_reorder = %d (%s)\n",
321          options->mlpReorder, dummy);
322
323  switch (options->mlpPreReorder) {
324  case 0 :
325    sprintf(dummy, "no reordering after clustering (default)");
326    break;
327  case 1 :
328    sprintf(dummy, "reorder using MLP after clustering (inside)");
329    break;
330  case 2 :
331    sprintf(dummy, "reorder using MLP after clustering (outside)");
332    break;
333  case 3 :
334    sprintf(dummy, "reorder using IWLS95 after clustering");
335    break;
336  default :
337    sprintf(dummy, "invalid");
338    break;
339  }
340  fprintf(vis_stdout, "MLP: mlp_pre_reorder = %d (%s)\n",
341          options->mlpPreReorder, dummy);
342
343  switch (options->mlpPostProcess) {
344  case 0 :
345    sprintf(dummy, "no postprocessing (default)");
346    break;
347  case 1 :
348    sprintf(dummy, "do postprocessing after ordering");
349    break;
350  case 2 :
351    sprintf(dummy, "do postprocessing after clustering or reordering");
352    break;
353  case 3 :
354    sprintf(dummy, "do both 1 and 2");
355    break;
356  default :
357    sprintf(dummy, "invalid");
358    break;
359  }
360  fprintf(vis_stdout, "MLP: mlp_postprocess = %d (%s)\n",
361          options->mlpPostProcess, dummy);
362}
363
364
365/*---------------------------------------------------------------------------*/
366/* Definition of internal functions                                          */
367/*---------------------------------------------------------------------------*/
368
369
370/**Function********************************************************************
371
372  Synopsis    [Performs multiway and_smooth using MLP.]
373
374  Description [Performs multiway and_smooth using MLP.]
375
376  SideEffects []
377
378******************************************************************************/
379bdd_t *
380ImgMlpMultiwayAndSmooth(mdd_manager *mddManager,
381                        ImgFunctionData_t *functionData,
382                        array_t *relationArray,
383                        array_t *domainVarBddArray,
384                        array_t *quantifyVarBddArray,
385                        array_t *rangeVarBddArray,
386                        Img_DirectionType direction,
387                        ImgTrmOption_t *option)
388{
389  int           i, clusterSize;
390  array_t       *clusteredRelationArray;
391  mdd_t         *result, *relation, *tmp;
392
393  if (direction == Img_Forward_c) {
394    if (array_n(domainVarBddArray) == 0 && array_n(quantifyVarBddArray) == 0) {
395      if (array_n(relationArray) == 1) {
396        relation = array_fetch(mdd_t *, relationArray, 0);
397        result = bdd_dup(relation);
398      } else {
399        result = array_fetch(mdd_t *, relationArray, 0);
400        for (i = 1; i < array_n(relationArray); i++) {
401          relation = array_fetch(mdd_t *, relationArray, i);
402          tmp = result;
403          result = bdd_and(tmp, relation, 1, 1);
404          mdd_free(tmp);
405        }
406      }
407      return(result);
408    }
409  }
410
411  clusterSize = option->clusterSize;
412  option->clusterSize = 1000000000;
413  ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
414                domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
415                direction, &clusteredRelationArray, NIL(array_t *), option);
416  option->clusterSize = clusterSize;
417
418  assert(array_n(clusteredRelationArray) == 1);
419  result = array_fetch(mdd_t *, clusteredRelationArray, 0);
420  array_free(clusteredRelationArray);
421
422  return(result);
423}
424
425
426/**Function********************************************************************
427
428  Synopsis    [Clusters relation array and makes quantification schedule.]
429
430  Description [Orders and clusters relation array and makes quantification
431  schedule. (Order/Cluster.)]
432
433  Description []
434
435  SideEffects [ImgClusterRelationArray]
436
437******************************************************************************/
438void
439ImgMlpClusterRelationArray(mdd_manager *mddManager,
440                        ImgFunctionData_t *functionData,
441                        array_t *relationArray,
442                        array_t *domainVarBddArray,
443                        array_t *quantifyVarBddArray,
444                        array_t *rangeVarBddArray,
445                        Img_DirectionType direction,
446                        array_t **clusteredRelationArrayPtr,
447                        array_t **arraySmoothVarBddArrayPtr,
448                        ImgTrmOption_t *option)
449{
450  int           i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
451  int           *rowOrder, *colOrder, *cRowOrder;
452  RcInfo_t      *rowInfo, *colInfo;
453  char          **xy;
454  int           nClusterRows, nClusterCols;
455  array_t       *clusterArray;
456  bdd_t         *cluster, *relation, *tempCluster, *var, *nsVar;
457  int           row, col, s, t;
458  array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
459  int           qVarPos;
460  array_t       *nonAppearingVarBddArray;
461  int           *varPos;
462  array_t       *psVarBddArray, *nsVarBddArray;
463  int           index, nVars, nc;
464  long          initialTime, finalTime;
465  array_t       *clusteredRelationArray;
466  SccList_t     *sccHeadList, *sccList;
467  int           *sccBorder;
468  float         lambda1, lambda2, lambda3;
469  FILE          *fout;
470
471  if (option->mlpVerbosity)
472    initialTime = util_cpu_time();
473  else
474    initialTime = 0;
475
476  psVarBddArray = domainVarBddArray;
477  nsVarBddArray = rangeVarBddArray;
478
479  if (option->mlpInitialCluster && functionData) {
480    clusteredRelationArray = CreateInitialCluster(mddManager, relationArray,
481                                                  functionData, nsVarBddArray,
482                                                  option);
483  } else
484    clusteredRelationArray = relationArray;
485
486  nRows = array_n(clusteredRelationArray);
487  if (direction == Img_Forward_c)
488    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
489  else
490    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
491
492  xy = ALLOC(char *, nRows);
493  for (i = 0; i < nRows; i++) {
494    xy[i] = ALLOC(char, nCols);
495    memset(xy[i], 0, sizeof(char) * nCols);
496  }
497
498  rowOrder = ALLOC(int, nRows);
499  for (i = 0; i < nRows; i++)
500    rowOrder[i] = i;
501  colOrder = ALLOC(int, nCols);
502  for (i = 0; i < nCols; i++)
503    colOrder[i] = i;
504
505  rowInfo = ALLOC(RcInfo_t, nRows);
506  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
507  colInfo = ALLOC(RcInfo_t, nCols);
508  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
509  nVars = bdd_num_vars(mddManager);
510  varPos = ALLOC(int, nVars);
511  memset(varPos, 0, sizeof(int) * nVars);
512
513  for (i = 0; i < nRows; i++) {
514    relation = array_fetch(bdd_t *, clusteredRelationArray, i);
515    rowInfo[i].data.row.func = bdd_dup(relation);
516  }
517
518  nc = 0;
519  for (i = 0; i < array_n(psVarBddArray); i++) {
520    var = array_fetch(bdd_t *, psVarBddArray, i);
521    colInfo[nc].data.col.var = var;
522    colInfo[nc].data.col.type = 1;
523    index = (int)bdd_top_var_id(var);
524    varPos[index] = nc;
525    nc++;
526  }
527  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
528    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
529    colInfo[nc].data.col.var = var;
530    colInfo[nc].data.col.type = 2;
531    index = (int)bdd_top_var_id(var);
532    varPos[index] = nc;
533    nc++;
534  }
535
536  if (arraySmoothVarBddArrayPtr)
537    nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
538  else
539    nonAppearingVarBddArray = NIL(array_t);
540
541  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
542           rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
543           nonAppearingVarBddArray, direction, option);
544
545  if (nActiveRows == 0) {
546    clusterArray = array_alloc(mdd_t *, 0);
547    cluster = bdd_one(mddManager);
548    for (i = nActiveRows; i < nRows; i++) {
549      row = rowOrder[i];
550      relation = rowInfo[row].data.row.func;
551      tempCluster = bdd_and(cluster, relation, 1, 1);
552      bdd_free(cluster);
553      cluster = tempCluster;
554    }
555    array_insert_last(bdd_t *, clusterArray, cluster);
556    *clusteredRelationArrayPtr = clusterArray;
557
558    if (arraySmoothVarBddArrayPtr) {
559      arraySmoothVarBddArray = array_alloc(array_t *, 0);
560      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
561      array_insert_last(array_t *, arraySmoothVarBddArray,
562                        nonAppearingVarBddArray);
563      if (direction == Img_Forward_c) {
564        smoothVarBddArray = array_alloc(array_t *, 0);
565        array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
566      } else {
567        smoothVarBddArray = array_alloc(array_t *, 0);
568        for (i = 0; i < nRows; i++) {
569          row = rowOrder[i];
570          for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
571            nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
572                                j);
573            array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
574          }
575        }
576        array_insert_last(array_t *, arraySmoothVarBddArray,
577                          smoothVarBddArray);
578      }
579    }
580
581    FREE(varPos);
582    for (i = 0; i < nRows; i++) {
583      if (xy[i])
584        FREE(xy[i]);
585    }
586    FREE(xy);
587    FREE(rowOrder);
588    FREE(colOrder);
589    for (i = 0; i < nRows; i++) {
590      bdd_free(rowInfo[i].data.row.func);
591      if (rowInfo[i].data.row.nsVarBddArray)
592        array_free(rowInfo[i].data.row.nsVarBddArray);
593    }
594    FREE(rowInfo);
595    FREE(colInfo);
596    return;
597  }
598  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
599                                rowOrder, colOrder, rowInfo, colInfo,
600                                0, option);
601  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
602    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
603                rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
604  }
605  sccList = sccHeadList;
606  while (sccList) {
607    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
608                        rowOrder, colOrder, rowInfo, colInfo, option);
609    sccList = sccList->next;
610  }
611  if (option->mlpVerbosity >= 2) {
612    lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
613                                rowInfo, colInfo, rowOrder, colOrder,
614                                direction, 0, 0, option);
615    lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
616                                rowInfo, colInfo, rowOrder, colOrder,
617                                direction, 1, 0, option);
618    lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
619                                rowInfo, colInfo, rowOrder, colOrder,
620                                direction, 2, 0, option);
621    fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
622            lambda1, lambda2, lambda3);
623  }
624
625  if (option->mlpVerbosity) {
626    finalTime = util_cpu_time();
627    fprintf(vis_stdout, "time for MLP = %10g\n",
628           (double)(finalTime - initialTime) / 1000.0);
629  }
630  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
631    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
632                rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
633  }
634
635  if (option->mlpPostProcess == 1 || option->mlpPostProcess == 3) {
636    for (x = 0; x < nActiveRows; x++) {
637      row = rowOrder[x];
638      rowInfo[row].lNum = rowInfo[row].gNum;
639      rowInfo[row].lMin = rowInfo[row].gMin;
640      rowInfo[row].lMax = rowInfo[row].gMax;
641      rowInfo[row].prevG = -1;
642      rowInfo[row].nextG = nActiveCols;
643    }
644    for (y = 0; y < nActiveCols; y++) {
645      col = colOrder[y];
646      colInfo[col].lNum = colInfo[col].gNum;
647      colInfo[col].lMin = colInfo[col].gMin;
648      colInfo[col].lMax = colInfo[col].gMax;
649      colInfo[col].prevG = -1;
650      colInfo[col].nextG = nActiveRows;
651    }
652
653    sccList = sccHeadList;
654    while (sccList) {
655      MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
656                   rowInfo, colInfo, rowOrder, colOrder, direction, option);
657      sccList = sccList->next;
658    }
659    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
660      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
661                  rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
662    }
663  }
664
665  if (option->mlpWriteOrder) {
666    fout = fopen(option->mlpWriteOrder, "w");
667    if (fout) {
668      WriteOrder(fout, nActiveCols, colOrder, colInfo);
669      fclose(fout);
670    } else {
671      fprintf(vis_stderr, "** img error: can't open file [%s]\n",
672              option->mlpWriteOrder);
673    }
674  }
675
676  clusterArray = array_alloc(bdd_t *, 0);
677  if (arraySmoothVarBddArrayPtr) {
678    arraySmoothVarBddArray = array_alloc(array_t *, 0);
679    array_insert_last(array_t *, arraySmoothVarBddArray,
680                        nonAppearingVarBddArray);
681  } else
682    arraySmoothVarBddArray = NIL(array_t);
683
684  if ((direction == Img_Forward_c && option->mlpReorder) ||
685      (direction == Img_Backward_c && option->mlpPreReorder) ||
686      option->mlpPostProcess >= 2) {
687    cRowOrder = ALLOC(int, nActiveRows);
688    for (i = 0; i < nActiveCols; i++) {
689      col = colOrder[i];
690      colInfo[col].lNum = 0;
691      colInfo[col].lMin = nActiveRows;
692      colInfo[col].lMax = -1;
693    }
694  } else
695    cRowOrder = NIL(int);
696
697  if (option->mlpClusterScc) {
698    sccBorder = ALLOC(int, nRows);
699    memset(sccBorder, 0, sizeof(int) * nRows);
700    sccList = sccHeadList;
701    while (sccList) {
702      sccBorder[sccList->startFunc] = 1;
703      sccBorder[sccList->lastFunc] = 2;
704      sccList = sccList->next;
705    }
706  } else
707    sccBorder = NIL(int);
708
709  MlpCluster(mddManager, xy, nRows, nCols, nActiveRows, nActiveCols,
710                &nClusterRows, &nClusterCols,
711                rowOrder, colOrder, rowInfo, colInfo,
712                clusterArray, arraySmoothVarBddArray,
713                direction, cRowOrder, nsVarBddArray, sccBorder, varPos, option);
714
715  if (sccBorder)
716    FREE(sccBorder);
717
718  if ((direction == Img_Forward_c && option->mlpReorder) ||
719      (direction == Img_Backward_c && option->mlpPreReorder) ||
720      option->mlpPostProcess >= 2) {
721    if (option->mlpDecomposeScc && NumOfSccs(sccHeadList) > 1) {
722      FreeSccList(sccHeadList);
723      sccHeadList = MlpDecomposeScc(mddManager, xy, nRows,
724                                nClusterRows, nClusterCols,
725                                cRowOrder, colOrder, rowInfo, colInfo,
726                                1, option);
727    } else {
728      sccHeadList->startFunc = 0;
729      sccHeadList->lastFunc = nClusterRows - 1;
730      sccHeadList->startVar = 0;
731      sccHeadList->lastVar = nClusterCols - 1;
732      sccHeadList->nFuncs = nClusterRows;
733      sccHeadList->nVars = nClusterCols;
734    }
735    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
736      PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
737                  rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
738    }
739
740    if ((direction == Img_Forward_c && option->mlpReorder) ||
741        (direction == Img_Backward_c && option->mlpPreReorder)) {
742      sccList = sccHeadList;
743      while (sccList) {
744        BlockLowerTriangle(xy, nRows, nCols, nClusterRows, nClusterCols,
745                           sccList, cRowOrder, colOrder, rowInfo, colInfo,
746                           option);
747        sccList = sccList->next;
748      }
749      if (option->mlpVerbosity >= 2) {
750        lambda1 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
751                                   rowInfo, colInfo, rowOrder, colOrder,
752                                   direction, 0, 0, option);
753        lambda2 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
754                                   rowInfo, colInfo, rowOrder, colOrder,
755                                   direction, 1, 0, option);
756        lambda3 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
757                                   rowInfo, colInfo, rowOrder, colOrder,
758                                   direction, 2, 0, option);
759        fprintf(vis_stdout, "Lambda after MLP-cluster = %f (%f, %f)\n",
760                lambda1, lambda2, lambda3);
761      }
762
763      if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
764        PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
765                    rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
766      }
767    }
768
769    if (option->mlpPostProcess >= 2) {
770      for (x = 0; x < nClusterRows; x++) {
771        row = rowOrder[x];
772        rowInfo[row].lNum = rowInfo[row].gNum;
773        rowInfo[row].lMin = rowInfo[row].gMin;
774        rowInfo[row].lMax = rowInfo[row].gMax;
775        rowInfo[row].prevG = -1;
776        rowInfo[row].nextG = nClusterCols;
777      }
778      for (y = 0; y < nClusterCols; y++) {
779        col = colOrder[y];
780        colInfo[col].lNum = colInfo[col].gNum;
781        colInfo[col].lMin = colInfo[col].gMin;
782        colInfo[col].lMax = colInfo[col].gMax;
783        colInfo[col].prevG = -1;
784        colInfo[col].nextG = nClusterRows;
785      }
786
787      sccList = sccHeadList;
788      while (sccList) {
789        MlpPostProcess(xy, sccList, nCols, nClusterRows, nClusterCols,
790                     rowInfo, colInfo, cRowOrder, colOrder, direction, option);
791        sccList = sccList->next;
792      }
793      if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
794        PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
795                    rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
796      }
797    }
798
799    *clusteredRelationArrayPtr = clusterArray;
800
801    if (direction == Img_Forward_c) {
802      for (i = nClusterRows - 1; i >= 0; i--) {
803        row = cRowOrder[i];
804        array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
805        rowInfo[row].data.row.func = NIL(bdd_t);
806      }
807
808      if (nRows > nActiveRows) {
809        cluster = bdd_one(mddManager);
810        for (i = nActiveRows; i < nRows; i++) {
811          row = rowOrder[i];
812          relation = rowInfo[row].data.row.func;
813          tempCluster = bdd_and(cluster, relation, 1, 1);
814          bdd_free(cluster);
815          cluster = tempCluster;
816        }
817        array_insert_last(bdd_t *, clusterArray, cluster);
818      }
819    } else {
820      if (nRows > nActiveRows) {
821        UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
822                                 rowInfo, cRowOrder, nonAppearingVarBddArray);
823
824        cluster = bdd_one(mddManager);
825        for (i = nActiveRows; i < nRows; i++) {
826          row = rowOrder[i];
827          relation = rowInfo[row].data.row.func;
828          tempCluster = bdd_and(cluster, relation, 1, 1);
829          bdd_free(cluster);
830          cluster = tempCluster;
831        }
832        array_insert_last(bdd_t *, clusterArray, cluster);
833      }
834
835      for (i = 0; i < nClusterRows; i++) {
836        row = cRowOrder[i];
837        array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
838        rowInfo[row].data.row.func = NIL(bdd_t);
839      }
840    }
841
842    if (arraySmoothVarBddArrayPtr) {
843      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
844
845      if (direction == Img_Forward_c) {
846        if (nCols > nClusterCols) {
847          for (i = nClusterCols; i < nCols; i++) {
848            col = colOrder[i];
849            array_insert_last(bdd_t *, nonAppearingVarBddArray,
850                                bdd_dup(colInfo[col].data.col.var));
851          }
852        }
853        qVarPos = nClusterCols - 1;
854        if (qVarPos >= 0) {
855          col = colOrder[qVarPos];
856          while (colInfo[col].gNum == 0) {
857            array_insert_last(bdd_t *, nonAppearingVarBddArray,
858                                bdd_dup(colInfo[col].data.col.var));
859            if (qVarPos == 0)
860              break;
861            qVarPos--;
862            col = colOrder[qVarPos];
863          }
864        }
865        for (i = nClusterRows - 1; i >= 0; i--) {
866          row = cRowOrder[i];
867          smoothVarBddArray = array_alloc(array_t *, 0);
868          col = colOrder[qVarPos];
869          while (rowInfo[colInfo[col].gMin].pos == i) {
870            array_insert_last(bdd_t *, smoothVarBddArray,
871                                bdd_dup(colInfo[col].data.col.var));
872            if (qVarPos == 0)
873              break;
874            qVarPos--;
875            col = colOrder[qVarPos];
876          }
877          array_insert_last(array_t *, arraySmoothVarBddArray,
878                            smoothVarBddArray);
879        }
880
881        if (nRows > nActiveRows) {
882          smoothVarBddArray = array_alloc(array_t *, 0);
883          array_insert_last(array_t *, arraySmoothVarBddArray,
884                            smoothVarBddArray);
885        }
886      } else {
887        if (nRows == nActiveRows) {
888          UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
889                                   rowInfo, cRowOrder, nonAppearingVarBddArray);
890        } else {
891          smoothVarBddArray = array_alloc(array_t *, 0);
892          for (i = nActiveRows; i < nRows; i++) {
893            row = rowOrder[i];
894            for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
895              nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
896                                  j);
897              array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
898            }
899          }
900          array_insert_last(array_t *, arraySmoothVarBddArray,
901                            smoothVarBddArray);
902        }
903        for (i = 0; i < nClusterRows; i++) {
904          row = cRowOrder[i];
905          smoothVarBddArray = array_alloc(array_t *, 0);
906          for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
907            nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
908                                j);
909            array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
910          }
911
912          s = colInfo[rowInfo[row].gMin].pos;
913          t = colInfo[rowInfo[row].gMax].pos;
914          for (j = s; j <= t; j++) {
915            col = colOrder[j];
916            if (colInfo[col].data.col.type == 2) {
917              if (rowInfo[colInfo[col].gMax].pos == i) {
918                array_insert_last(bdd_t *, smoothVarBddArray,
919                                  bdd_dup(colInfo[col].data.col.var));
920              }
921            }
922          }
923          array_insert_last(array_t *, arraySmoothVarBddArray,
924                            smoothVarBddArray);
925        }
926      }
927    }
928
929    FREE(cRowOrder);
930
931    if (option->mlpVerbosity) {
932      finalTime = util_cpu_time();
933      fprintf(vis_stdout, "time for MLP-clustering-reorder = %10g\n",
934              (double)(finalTime - initialTime) / 1000.0);
935    }
936  } else {
937    *clusteredRelationArrayPtr = clusterArray;
938    if (arraySmoothVarBddArrayPtr)
939      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
940
941    if (option->mlpVerbosity) {
942      finalTime = util_cpu_time();
943      fprintf(vis_stdout, "time for MLP-clustering = %10g\n",
944              (double)(finalTime - initialTime) / 1000.0);
945    }
946  }
947
948  FreeSccList(sccHeadList);
949
950  FREE(varPos);
951  for (i = 0; i < nRows; i++) {
952    if (xy[i])
953      FREE(xy[i]);
954  }
955  FREE(xy);
956  FREE(rowOrder);
957  FREE(colOrder);
958  for (i = 0; i < nRows; i++) {
959    if (rowInfo[i].data.row.func)
960      bdd_free(rowInfo[i].data.row.func);
961    if (rowInfo[i].data.row.nsVarBddArray)
962      array_free(rowInfo[i].data.row.nsVarBddArray);
963  }
964  FREE(rowInfo);
965  FREE(colInfo);
966  if (option->mlpInitialCluster)
967    mdd_array_free(clusteredRelationArray);
968}
969
970
971/**Function********************************************************************
972
973  Synopsis    [Orders relation array and makes quantification schedule.]
974
975  Description [Orders relation array and makes quantification schedule.]
976
977  SideEffects []
978
979******************************************************************************/
980void
981ImgMlpOrderRelationArray(mdd_manager *mddManager,
982                        array_t *relationArray,
983                        array_t *domainVarBddArray,
984                        array_t *quantifyVarBddArray,
985                        array_t *rangeVarBddArray,
986                        Img_DirectionType direction,
987                        array_t **orderedRelationArrayPtr,
988                        array_t **arraySmoothVarBddArrayPtr,
989                        ImgTrmOption_t *option)
990{
991  int           i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
992  int           *rowOrder, *colOrder;
993  RcInfo_t      *rowInfo, *colInfo;
994  char          **xy;
995  array_t       *orderedArray;
996  bdd_t         *relation, *var, *nsVar;
997  int           row, col, s, t;
998  array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
999  int           qVarPos;
1000  array_t       *nonAppearingVarBddArray;
1001  int           *varPos;
1002  array_t       *psVarBddArray, *nsVarBddArray;
1003  int           index, nVars, nc;
1004  long          initialTime, finalTime;
1005  SccList_t     *sccHeadList, *sccList;
1006  float         lambda1, lambda2, lambda3;
1007
1008  arraySmoothVarBddArray = NIL(array_t);
1009  nRows = array_n(relationArray);
1010  if (direction == Img_Forward_c)
1011    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
1012  else
1013    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
1014
1015  if (nCols == 0) {
1016    if (direction == Img_Forward_c) {
1017      orderedArray = mdd_array_duplicate(relationArray);
1018      *orderedRelationArrayPtr = orderedArray;
1019      if (arraySmoothVarBddArrayPtr) {
1020        arraySmoothVarBddArray = array_alloc(array_t *, 0);
1021        *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
1022        for (i = 0; i <= nRows; i++) {
1023          smoothVarBddArray = array_alloc(array_t *, 0);
1024          array_insert_last(array_t *, arraySmoothVarBddArray,
1025                            smoothVarBddArray);
1026        }
1027      }
1028    } else {
1029      orderedArray = array_alloc(mdd_t *, 0);
1030      array_insert_last(mdd_t *, orderedArray, mdd_one(mddManager));
1031      *orderedRelationArrayPtr = orderedArray;
1032      if (arraySmoothVarBddArrayPtr) {
1033        arraySmoothVarBddArray = array_alloc(array_t *, 0);
1034        *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
1035        for (i = 0; i <= 1; i++) {
1036          smoothVarBddArray = array_alloc(array_t *, 0);
1037          array_insert_last(array_t *, arraySmoothVarBddArray,
1038                            smoothVarBddArray);
1039        }
1040      }
1041    }
1042    return;
1043  }
1044
1045  if (option->mlpVerbosity)
1046    initialTime = util_cpu_time();
1047  else
1048    initialTime = 0;
1049
1050  xy = ALLOC(char *, nRows);
1051  for (i = 0; i < nRows; i++) {
1052    xy[i] = ALLOC(char, nCols);
1053    memset(xy[i], 0, sizeof(char) * nCols);
1054  }
1055
1056  rowOrder = ALLOC(int, nRows);
1057  for (i = 0; i < nRows; i++)
1058    rowOrder[i] = i;
1059  colOrder = ALLOC(int, nCols);
1060  for (i = 0; i < nCols; i++)
1061    colOrder[i] = i;
1062
1063  rowInfo = ALLOC(RcInfo_t, nRows);
1064  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
1065  colInfo = ALLOC(RcInfo_t, nCols);
1066  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
1067  nVars = bdd_num_vars(mddManager);
1068  varPos = ALLOC(int, nVars);
1069  memset(varPos, 0, sizeof(int) * nVars);
1070
1071  for (i = 0; i < nRows; i++) {
1072    relation = array_fetch(bdd_t *, relationArray, i);
1073    rowInfo[i].data.row.func = bdd_dup(relation);
1074  }
1075
1076  psVarBddArray = domainVarBddArray;
1077  nsVarBddArray = rangeVarBddArray;
1078  nc = 0;
1079  for (i = 0; i < array_n(psVarBddArray); i++) {
1080    var = array_fetch(bdd_t *, psVarBddArray, i);
1081    colInfo[nc].data.col.var = var;
1082    colInfo[nc].data.col.type = 1;
1083    index = (int)bdd_top_var_id(var);
1084    varPos[index] = nc;
1085    nc++;
1086  }
1087  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
1088    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
1089    colInfo[nc].data.col.var = var;
1090    colInfo[nc].data.col.type = 2;
1091    index = (int)bdd_top_var_id(var);
1092    varPos[index] = nc;
1093    nc++;
1094  }
1095
1096  if (arraySmoothVarBddArrayPtr)
1097    nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
1098  else
1099    nonAppearingVarBddArray = NIL(array_t);
1100  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
1101           rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
1102           nonAppearingVarBddArray, direction, option);
1103  if (nActiveRows == 0) {
1104    orderedArray = array_alloc(bdd_t *, 0);
1105    if (arraySmoothVarBddArrayPtr) {
1106      arraySmoothVarBddArray = array_alloc(array_t *, 0);
1107      array_insert_last(array_t *, arraySmoothVarBddArray,
1108                        nonAppearingVarBddArray);
1109    }
1110    for (i = 0; i < nRows; i++) {
1111      row = rowOrder[i];
1112      relation = rowInfo[row].data.row.func;
1113      array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
1114      if (arraySmoothVarBddArrayPtr) {
1115        if (direction == Img_Forward_c) {
1116          smoothVarBddArray = array_alloc(array_t *, 0);
1117          array_insert_last(array_t *, arraySmoothVarBddArray,
1118                            smoothVarBddArray);
1119        } else {
1120          smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
1121          rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
1122          array_insert_last(array_t *, arraySmoothVarBddArray,
1123                            smoothVarBddArray);
1124        }
1125      }
1126    }
1127    *orderedRelationArrayPtr = orderedArray;
1128    if (arraySmoothVarBddArrayPtr)
1129      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
1130
1131    FREE(varPos);
1132    for (i = 0; i < nRows; i++) {
1133      if (xy[i])
1134        FREE(xy[i]);
1135    }
1136    FREE(xy);
1137    FREE(rowOrder);
1138    FREE(colOrder);
1139    for (i = 0; i < nRows; i++) {
1140      bdd_free(rowInfo[i].data.row.func);
1141      if (rowInfo[i].data.row.nsVarBddArray)
1142        array_free(rowInfo[i].data.row.nsVarBddArray);
1143    }
1144    FREE(rowInfo);
1145    FREE(colInfo);
1146    return;
1147  }
1148  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
1149                                rowOrder, colOrder, rowInfo, colInfo,
1150                                0, option);
1151  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
1152    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
1153                rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
1154  }
1155  sccList = sccHeadList;
1156  while (sccList) {
1157    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
1158                        rowOrder, colOrder, rowInfo, colInfo, option);
1159    sccList = sccList->next;
1160  }
1161  if (option->mlpVerbosity >= 2) {
1162    lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1163                                rowInfo, colInfo, rowOrder, colOrder,
1164                                direction, 0, 0, option);
1165    lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1166                                rowInfo, colInfo, rowOrder, colOrder,
1167                                direction, 1, 0, option);
1168    lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1169                                rowInfo, colInfo, rowOrder, colOrder,
1170                                direction, 2, 0, option);
1171    fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
1172            lambda1, lambda2, lambda3);
1173  }
1174
1175  if (option->mlpVerbosity) {
1176    finalTime = util_cpu_time();
1177    fprintf(vis_stdout, "time for MLP = %10g\n",
1178           (double)(finalTime - initialTime) / 1000.0);
1179  }
1180  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
1181    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
1182                rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
1183  }
1184
1185  if (option->mlpPostProcess) {
1186    for (x = 0; x < nRows; x++) {
1187      row = rowOrder[x];
1188      rowInfo[row].lNum = rowInfo[row].gNum;
1189      rowInfo[row].lMin = rowInfo[row].gMin;
1190      rowInfo[row].lMax = rowInfo[row].gMax;
1191      rowInfo[row].prevG = -1;
1192      rowInfo[row].nextG = nCols;
1193    }
1194    for (y = 0; y < nCols; y++) {
1195      col = colOrder[y];
1196      colInfo[col].lNum = colInfo[col].gNum;
1197      colInfo[col].lMin = colInfo[col].gMin;
1198      colInfo[col].lMax = colInfo[col].gMax;
1199      colInfo[col].prevG = -1;
1200      colInfo[col].nextG = nRows;
1201    }
1202
1203    sccList = sccHeadList;
1204    while (sccList) {
1205      MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
1206                   rowInfo, colInfo, rowOrder, colOrder, direction, option);
1207      sccList = sccList->next;
1208    }
1209    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
1210      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
1211                  rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
1212    }
1213  }
1214
1215  orderedArray = array_alloc(bdd_t *, 0);
1216  if (arraySmoothVarBddArrayPtr) {
1217    arraySmoothVarBddArray = array_alloc(array_t *, 0);
1218    array_insert_last(array_t *, arraySmoothVarBddArray,
1219                        nonAppearingVarBddArray);
1220  }
1221
1222  assert(nActiveCols > 0);
1223  if (direction == Img_Forward_c) {
1224    if (arraySmoothVarBddArrayPtr) {
1225      if (nCols > nActiveCols) {
1226        for (i = nActiveCols; i < nCols; i++) {
1227          col = colOrder[i];
1228          array_insert_last(bdd_t *, nonAppearingVarBddArray,
1229                            bdd_dup(colInfo[col].data.col.var));
1230        }
1231      }
1232      qVarPos = nActiveCols - 1;
1233      if (qVarPos >= 0) {
1234        col = colOrder[qVarPos];
1235        while (colInfo[col].gNum == 0) {
1236          array_insert_last(bdd_t *, nonAppearingVarBddArray,
1237                            bdd_dup(colInfo[col].data.col.var));
1238          if (qVarPos == 0)
1239            break;
1240          qVarPos--;
1241          col = colOrder[qVarPos];
1242        }
1243      }
1244    } else
1245      qVarPos = 0; /* to avoid warning */
1246    for (i = nActiveRows - 1; i >= 0; i--) {
1247      row = rowOrder[i];
1248      if (arraySmoothVarBddArrayPtr) {
1249        smoothVarBddArray = array_alloc(array_t *, 0);
1250        col = colOrder[qVarPos];
1251        while (rowInfo[colInfo[col].gMin].pos == i) {
1252          index = (int)bdd_top_var_id(colInfo[col].data.col.var);
1253          array_insert_last(bdd_t *, smoothVarBddArray,
1254                                bdd_dup(colInfo[col].data.col.var));
1255          if (qVarPos == 0)
1256            break;
1257          qVarPos--;
1258          col = colOrder[qVarPos];
1259        }
1260        array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1261      }
1262      relation = bdd_dup(rowInfo[row].data.row.func);
1263      array_insert_last(bdd_t *, orderedArray, relation);
1264    }
1265
1266    if (nRows > nActiveRows) {
1267      for (i = nActiveRows; i < nRows; i++) {
1268        row = rowOrder[i];
1269        relation = rowInfo[row].data.row.func;
1270        array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
1271        if (arraySmoothVarBddArrayPtr) {
1272          smoothVarBddArray = array_alloc(array_t *, 0);
1273          array_insert_last(array_t *, arraySmoothVarBddArray,
1274                            smoothVarBddArray);
1275        }
1276      }
1277    }
1278  } else {
1279    if (arraySmoothVarBddArrayPtr) {
1280      UpdateNonappearingNsVars(mddManager, nsVarBddArray, nActiveRows,
1281                                rowInfo, rowOrder, nonAppearingVarBddArray);
1282    }
1283    if (nRows > nActiveRows) {
1284      for (i = nActiveRows; i < nRows; i++) {
1285        row = rowOrder[i];
1286        relation = rowInfo[row].data.row.func;
1287        array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
1288        if (arraySmoothVarBddArrayPtr) {
1289          smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
1290          rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
1291          array_insert_last(array_t *, arraySmoothVarBddArray,
1292                            smoothVarBddArray);
1293        }
1294      }
1295    }
1296    for (i = 0; i < nActiveRows; i++) {
1297      row = rowOrder[i];
1298      if (arraySmoothVarBddArrayPtr) {
1299        smoothVarBddArray = array_alloc(array_t *, 0);
1300        for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
1301          nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
1302          array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
1303        }
1304
1305        s = colInfo[rowInfo[row].gMin].pos;
1306        t = colInfo[rowInfo[row].gMax].pos;
1307        for (j = s; j <= t; j++) {
1308          col = colOrder[j];
1309          if (colInfo[col].data.col.type == 2) {
1310            if (rowInfo[colInfo[col].gMax].pos == i) {
1311              array_insert_last(bdd_t *, smoothVarBddArray,
1312                                bdd_dup(colInfo[col].data.col.var));
1313            }
1314          }
1315        }
1316        array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1317      }
1318      relation = bdd_dup(rowInfo[row].data.row.func);
1319      array_insert_last(bdd_t *, orderedArray, relation);
1320    }
1321  }
1322
1323  *orderedRelationArrayPtr = orderedArray;
1324  if (arraySmoothVarBddArrayPtr)
1325    *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
1326
1327  FreeSccList(sccHeadList);
1328
1329  FREE(varPos);
1330  for (i = 0; i < nRows; i++) {
1331    if (xy[i])
1332      FREE(xy[i]);
1333  }
1334  FREE(xy);
1335  FREE(rowOrder);
1336  FREE(colOrder);
1337  for (i = 0; i < nRows; i++) {
1338    bdd_free(rowInfo[i].data.row.func);
1339    if (rowInfo[i].data.row.nsVarBddArray)
1340      array_free(rowInfo[i].data.row.nsVarBddArray);
1341  }
1342  FREE(rowInfo);
1343  FREE(colInfo);
1344}
1345
1346
1347/**Function********************************************************************
1348
1349  Synopsis    [Compute variables lifetime using MLP.]
1350
1351  Description [Compute variables lifetime using MLP.]
1352
1353  SideEffects []
1354
1355******************************************************************************/
1356float
1357ImgMlpComputeLambda(mdd_manager *mddManager,
1358                    array_t *relationArray,
1359                    array_t *domainVarBddArray,
1360                    array_t *quantifyVarBddArray,
1361                    array_t *rangeVarBddArray,
1362                    Img_DirectionType direction,
1363                    int mode,
1364                    int asIs,
1365                    int *prevArea,
1366                    float *improvedLambda,
1367                    ImgTrmOption_t *option)
1368{
1369  int           i, nRows, nCols, nActiveRows, nActiveCols;
1370  int           *rowOrder, *colOrder;
1371  RcInfo_t      *rowInfo, *colInfo;
1372  char          **xy;
1373  bdd_t         *relation, *var;
1374  int           *varPos;
1375  array_t       *psVarBddArray, *nsVarBddArray;
1376  int           index, nVars, nc;
1377  SccList_t     *sccHeadList, *sccList;
1378  float         lambda;
1379  int           area;
1380
1381  nRows = array_n(relationArray);
1382  if (direction == Img_Forward_c)
1383    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
1384  else
1385    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
1386
1387  if (nCols == 0) {
1388    if (improvedLambda) {
1389      *improvedLambda = 0.0;
1390      *prevArea = 0;
1391    }
1392    return(0.0);
1393  }
1394
1395  xy = ALLOC(char *, nRows);
1396  for (i = 0; i < nRows; i++) {
1397    xy[i] = ALLOC(char, nCols);
1398    memset(xy[i], 0, sizeof(char) * nCols);
1399  }
1400
1401  rowOrder = ALLOC(int, nRows);
1402  for (i = 0; i < nRows; i++)
1403    rowOrder[i] = i;
1404  colOrder = ALLOC(int, nCols);
1405  for (i = 0; i < nCols; i++)
1406    colOrder[i] = i;
1407
1408  rowInfo = ALLOC(RcInfo_t, nRows);
1409  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
1410  colInfo = ALLOC(RcInfo_t, nCols);
1411  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
1412  nVars = bdd_num_vars(mddManager);
1413  varPos = ALLOC(int, nVars);
1414  memset(varPos, 0, sizeof(int) * nVars);
1415
1416  for (i = 0; i < nRows; i++) {
1417    relation = array_fetch(bdd_t *, relationArray, i);
1418    rowInfo[i].data.row.func = bdd_dup(relation);
1419  }
1420
1421  psVarBddArray = domainVarBddArray;
1422  nsVarBddArray = rangeVarBddArray;
1423  nc = 0;
1424  for (i = 0; i < array_n(psVarBddArray); i++) {
1425    var = array_fetch(bdd_t *, psVarBddArray, i);
1426    colInfo[nc].data.col.var = var;
1427    colInfo[nc].data.col.type = 1;
1428    index = (int)bdd_top_var_id(var);
1429    varPos[index] = nc;
1430    nc++;
1431  }
1432  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
1433    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
1434    colInfo[nc].data.col.var = var;
1435    colInfo[nc].data.col.type = 2;
1436    index = (int)bdd_top_var_id(var);
1437    varPos[index] = nc;
1438    nc++;
1439  }
1440
1441  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
1442           rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
1443           NIL(array_t), direction, option);
1444  if (nActiveRows == 0) {
1445    FREE(varPos);
1446    for (i = 0; i < nRows; i++) {
1447      if (xy[i])
1448        FREE(xy[i]);
1449    }
1450    FREE(xy);
1451    FREE(rowOrder);
1452    FREE(colOrder);
1453    for (i = 0; i < nRows; i++) {
1454      bdd_free(rowInfo[i].data.row.func);
1455      if (rowInfo[i].data.row.nsVarBddArray)
1456        array_free(rowInfo[i].data.row.nsVarBddArray);
1457    }
1458    FREE(rowInfo);
1459    FREE(colInfo);
1460
1461    if (improvedLambda) {
1462      *improvedLambda = 0.0;
1463      *prevArea = 0;
1464    }
1465    return(0.0);
1466  }
1467  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
1468                                rowOrder, colOrder, rowInfo, colInfo,
1469                                0, option);
1470  sccList = sccHeadList;
1471  while (sccList) {
1472    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
1473                        rowOrder, colOrder, rowInfo, colInfo, option);
1474    sccList = sccList->next;
1475  }
1476
1477  lambda = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1478                            rowInfo, colInfo, rowOrder, colOrder,
1479                            direction, mode, asIs, option);
1480
1481  FreeSccList(sccHeadList);
1482
1483  FREE(varPos);
1484  for (i = 0; i < nRows; i++) {
1485    if (xy[i])
1486      FREE(xy[i]);
1487  }
1488  FREE(xy);
1489  FREE(rowOrder);
1490  FREE(colOrder);
1491  for (i = 0; i < nRows; i++) {
1492    bdd_free(rowInfo[i].data.row.func);
1493    if (rowInfo[i].data.row.nsVarBddArray)
1494      array_free(rowInfo[i].data.row.nsVarBddArray);
1495  }
1496  FREE(rowInfo);
1497  FREE(colInfo);
1498
1499  if (option->mlpLambdaMode == 0)
1500    area = nActiveRows * nActiveCols;
1501  else
1502    area = nActiveRows * nCols;
1503  if (improvedLambda) {
1504    if (*prevArea)
1505      *improvedLambda = lambda * (float)area / (*prevArea);
1506    else
1507      *improvedLambda = 0.0;
1508    *prevArea = area;
1509  }
1510  return(lambda);
1511}
1512
1513
1514/**Function********************************************************************
1515
1516  Synopsis    [Makes a quantification schedule using MLP.]
1517
1518  Description [Makes a quantification schedule using MLP.]
1519
1520  SideEffects []
1521
1522******************************************************************************/
1523void
1524ImgMlpGetQuantificationSchedule(mdd_manager *mddManager,
1525                        array_t *relationArray,
1526                        array_t *domainVarBddArray,
1527                        array_t *quantifyVarBddArray,
1528                        array_t *rangeVarBddArray,
1529                        array_t **clusteredRelationArrayPtr,
1530                        array_t **arraySmoothVarBddArrayPtr,
1531                        Img_DirectionType direction,
1532                        ImgTrmOption_t *option)
1533{
1534  int           i, j, nRows, nCols, nActiveRows, nActiveCols;
1535  int           *rowOrder, *colOrder;
1536  RcInfo_t      *rowInfo, *colInfo;
1537  char          **xy;
1538  bdd_t         *relation, *var, *nsVar;
1539  int           *varPos;
1540  array_t       *psVarBddArray, *nsVarBddArray;
1541  int           index, nVars, nc;
1542  array_t       *arraySmoothVarBddArray, *smoothVarBddArray;
1543  int           qVarPos, row, col, s, t;
1544  array_t       *nonAppearingVarBddArray;
1545  array_t       *clusteredRelationArray;
1546
1547  nRows = array_n(relationArray);
1548  if (direction == Img_Forward_c)
1549    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
1550  else
1551    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
1552
1553  xy = ALLOC(char *, nRows);
1554  for (i = 0; i < nRows; i++) {
1555    xy[i] = ALLOC(char, nCols);
1556    memset(xy[i], 0, sizeof(char) * nCols);
1557  }
1558
1559  rowOrder = ALLOC(int, nRows);
1560  for (i = 0; i < nRows; i++)
1561    rowOrder[i] = i;
1562  colOrder = ALLOC(int, nCols);
1563  for (i = 0; i < nCols; i++)
1564    colOrder[i] = i;
1565
1566  rowInfo = ALLOC(RcInfo_t, nRows);
1567  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
1568  colInfo = ALLOC(RcInfo_t, nCols);
1569  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
1570  nVars = bdd_num_vars(mddManager);
1571  varPos = ALLOC(int, nVars);
1572  memset(varPos, 0, sizeof(int) * nVars);
1573
1574  psVarBddArray = domainVarBddArray;
1575  nsVarBddArray = rangeVarBddArray;
1576  if (direction == Img_Forward_c) {
1577    for (i = 0; i < nRows; i++) {
1578      relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
1579      rowInfo[i].data.row.func = bdd_dup(relation);
1580    }
1581  } else {
1582    for (i = 0; i < nRows; i++) {
1583      relation = array_fetch(bdd_t *, relationArray, i);
1584      rowInfo[i].data.row.func = bdd_dup(relation);
1585    }
1586  }
1587  nc = 0;
1588  for (i = 0; i < array_n(psVarBddArray); i++) {
1589    var = array_fetch(bdd_t *, psVarBddArray, i);
1590    colInfo[nc].data.col.var = var;
1591    colInfo[nc].data.col.type = 1;
1592    index = (int)bdd_top_var_id(var);
1593    varPos[index] = nc;
1594    nc++;
1595  }
1596  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
1597    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
1598    colInfo[nc].data.col.var = var;
1599    colInfo[nc].data.col.type = 2;
1600    index = (int)bdd_top_var_id(var);
1601    varPos[index] = nc;
1602    nc++;
1603  }
1604
1605  nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
1606  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
1607           rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
1608           nonAppearingVarBddArray, direction, option);
1609  SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
1610
1611  clusteredRelationArray = array_alloc(mdd_t *, 0);
1612  arraySmoothVarBddArray = array_alloc(array_t *, 0);
1613  if (direction == Img_Forward_c) {
1614    if (nCols > nActiveCols) {
1615      for (i = nActiveCols; i < nCols; i++) {
1616        col = colOrder[i];
1617        array_insert_last(bdd_t *, nonAppearingVarBddArray,
1618                          bdd_dup(colInfo[col].data.col.var));
1619      }
1620    }
1621    qVarPos = nActiveCols - 1;
1622    if (qVarPos >= 0) {
1623      col = colOrder[qVarPos];
1624      while (colInfo[col].gNum == 0) {
1625        array_insert_last(bdd_t *, nonAppearingVarBddArray,
1626                          bdd_dup(colInfo[col].data.col.var));
1627        if (qVarPos == 0)
1628          break;
1629        qVarPos--;
1630        col = colOrder[qVarPos];
1631      }
1632    }
1633    array_insert_last(array_t *, arraySmoothVarBddArray,
1634                        nonAppearingVarBddArray);
1635    for (i = nActiveRows - 1; i >= 0; i--) {
1636      row = rowOrder[i];
1637      smoothVarBddArray = array_alloc(array_t *, 0);
1638      if (rowInfo[row].gNum > 0) {
1639        col = colOrder[qVarPos];
1640        while (rowInfo[colInfo[col].gMin].pos == i) {
1641          index = (int)bdd_top_var_id(colInfo[col].data.col.var);
1642          array_insert_last(bdd_t *, smoothVarBddArray,
1643                                bdd_dup(colInfo[col].data.col.var));
1644          if (qVarPos == 0)
1645            break;
1646          qVarPos--;
1647          col = colOrder[qVarPos];
1648        }
1649      }
1650      array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1651      relation = bdd_dup(rowInfo[row].data.row.func);
1652      array_insert_last(bdd_t *, clusteredRelationArray, relation);
1653    }
1654    if (nRows > nActiveRows) {
1655      for (i = nActiveRows; i < nRows; i++) {
1656        row = rowOrder[i];
1657        smoothVarBddArray = array_alloc(array_t *, 0);
1658        array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1659        relation = bdd_dup(rowInfo[row].data.row.func);
1660        array_insert_last(bdd_t *, clusteredRelationArray, relation);
1661      }
1662    }
1663  } else {
1664    array_insert_last(array_t *, arraySmoothVarBddArray,
1665                        nonAppearingVarBddArray);
1666    if (nRows > nActiveRows) {
1667      for (i = nActiveRows; i < nRows; i++) {
1668        row = rowOrder[i];
1669        smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
1670        rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
1671        array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1672        relation = bdd_dup(rowInfo[row].data.row.func);
1673        array_insert_last(bdd_t *, clusteredRelationArray, relation);
1674      }
1675    }
1676    for (i = 0; i < nActiveRows; i++) {
1677      row = rowOrder[i];
1678      smoothVarBddArray = array_alloc(array_t *, 0);
1679      for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
1680        nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
1681        array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
1682      }
1683      if (rowInfo[row].gNum > 0) {
1684        s = colInfo[rowInfo[row].gMin].pos;
1685        t = colInfo[rowInfo[row].gMax].pos;
1686        for (j = s; j <= t; j++) {
1687          col = colOrder[j];
1688          if (colInfo[col].data.col.type == 2) {
1689            if (rowInfo[colInfo[col].gMax].pos == i) {
1690              array_insert_last(bdd_t *, smoothVarBddArray,
1691                                bdd_dup(colInfo[col].data.col.var));
1692            }
1693          }
1694        }
1695      }
1696      array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
1697      relation = bdd_dup(rowInfo[row].data.row.func);
1698      array_insert_last(bdd_t *, clusteredRelationArray, relation);
1699    }
1700  }
1701
1702  FREE(varPos);
1703  for (i = 0; i < nRows; i++) {
1704    if (xy[i])
1705      FREE(xy[i]);
1706  }
1707  FREE(xy);
1708  FREE(rowOrder);
1709  FREE(colOrder);
1710  for (i = 0; i < nRows; i++) {
1711    bdd_free(rowInfo[i].data.row.func);
1712    if (rowInfo[i].data.row.nsVarBddArray)
1713      array_free(rowInfo[i].data.row.nsVarBddArray);
1714  }
1715  FREE(rowInfo);
1716  FREE(colInfo);
1717
1718  *clusteredRelationArrayPtr = clusteredRelationArray;
1719  *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
1720}
1721
1722
1723/**Function********************************************************************
1724
1725  Synopsis    [Prints dependence matrix.]
1726
1727  Description [Prints dependence matrix.]
1728
1729  SideEffects []
1730
1731******************************************************************************/
1732void
1733ImgMlpPrintDependenceMatrix(mdd_manager *mddManager,
1734                        array_t *relationArray,
1735                        array_t *domainVarBddArray,
1736                        array_t *quantifyVarBddArray,
1737                        array_t *rangeVarBddArray,
1738                        Img_DirectionType direction,
1739                        int printFlag, FILE *fout,
1740                        ImgTrmOption_t *option)
1741{
1742  int           i, nRows, nCols, nActiveRows, nActiveCols;
1743  int           *rowOrder, *colOrder;
1744  RcInfo_t      *rowInfo, *colInfo;
1745  char          **xy;
1746  bdd_t         *relation, *var;
1747  int           *varPos;
1748  array_t       *psVarBddArray, *nsVarBddArray;
1749  int           index, nVars, nc;
1750  float         lambda1, lambda2, lambda3;
1751
1752  nRows = array_n(relationArray);
1753  if (direction == Img_Forward_c)
1754    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
1755  else
1756    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
1757
1758  xy = ALLOC(char *, nRows);
1759  for (i = 0; i < nRows; i++) {
1760    xy[i] = ALLOC(char, nCols);
1761    memset(xy[i], 0, sizeof(char) * nCols);
1762  }
1763
1764  rowOrder = ALLOC(int, nRows);
1765  for (i = 0; i < nRows; i++)
1766    rowOrder[i] = i;
1767  colOrder = ALLOC(int, nCols);
1768  for (i = 0; i < nCols; i++)
1769    colOrder[i] = i;
1770
1771  rowInfo = ALLOC(RcInfo_t, nRows);
1772  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
1773  colInfo = ALLOC(RcInfo_t, nCols);
1774  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
1775  nVars = bdd_num_vars(mddManager);
1776  varPos = ALLOC(int, nVars);
1777  memset(varPos, 0, sizeof(int) * nVars);
1778
1779  psVarBddArray = domainVarBddArray;
1780  nsVarBddArray = rangeVarBddArray;
1781  if (direction == Img_Forward_c) {
1782    for (i = 0; i < nRows; i++) {
1783      relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
1784      rowInfo[i].data.row.func = bdd_dup(relation);
1785    }
1786  } else {
1787    for (i = 0; i < nRows; i++) {
1788      relation = array_fetch(bdd_t *, relationArray, i);
1789      rowInfo[i].data.row.func = bdd_dup(relation);
1790    }
1791  }
1792  nc = 0;
1793  for (i = 0; i < array_n(psVarBddArray); i++) {
1794    var = array_fetch(bdd_t *, psVarBddArray, i);
1795    colInfo[nc].data.col.var = var;
1796    colInfo[nc].data.col.type = 1;
1797    index = (int)bdd_top_var_id(var);
1798    varPos[index] = nc;
1799    nc++;
1800  }
1801  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
1802    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
1803    colInfo[nc].data.col.var = var;
1804    colInfo[nc].data.col.type = 2;
1805    index = (int)bdd_top_var_id(var);
1806    varPos[index] = nc;
1807    nc++;
1808  }
1809
1810  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
1811           rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
1812           NIL(array_t), direction, option);
1813  SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
1814
1815  if (printFlag) {
1816    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
1817                rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
1818  }
1819  if (fout) {
1820    WriteMatrix(fout, xy, nActiveRows, nActiveCols, rowOrder, colOrder,
1821                rowInfo, colInfo);
1822  }
1823  lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1824                                rowInfo, colInfo, rowOrder, colOrder,
1825                                direction, 0, 0, option);
1826  lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1827                                rowInfo, colInfo, rowOrder, colOrder,
1828                                direction, 1, 0, option);
1829  lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
1830                                rowInfo, colInfo, rowOrder, colOrder,
1831                                direction, 2, 0, option);
1832  fprintf(vis_stdout, "Lambda = %f (%f, %f)\n", lambda1, lambda2, lambda3);
1833
1834  FREE(varPos);
1835  for (i = 0; i < nRows; i++) {
1836    if (xy[i])
1837      FREE(xy[i]);
1838  }
1839  FREE(xy);
1840  FREE(rowOrder);
1841  FREE(colOrder);
1842  for (i = 0; i < nRows; i++) {
1843    bdd_free(rowInfo[i].data.row.func);
1844    if (rowInfo[i].data.row.nsVarBddArray)
1845      array_free(rowInfo[i].data.row.nsVarBddArray);
1846  }
1847  FREE(rowInfo);
1848  FREE(colInfo);
1849}
1850
1851
1852/**Function********************************************************************
1853
1854  Synopsis    [Writes cluster to a file.]
1855
1856  Description [Writes cluster to a file.]
1857
1858  SideEffects []
1859
1860******************************************************************************/
1861void
1862ImgMlpWriteClusterFile(FILE *fout,
1863                        mdd_manager *mddManager,
1864                        array_t *relationArray,
1865                        array_t *psVarBddArray,
1866                        array_t *nsVarBddArray)
1867{
1868  int           i, j, k, nVars;
1869  int           bddId, mddId, id, index;
1870  mdd_t         *relation;
1871  mdd_t         *psVar, *nsVar, **nsVars, **ns2ps;
1872  array_t       *supportBddIdArray, *bddIdArray;
1873  char          *name;
1874  int           count;
1875
1876  nVars = bdd_num_vars(mddManager);
1877  nsVars = ALLOC(bdd_t *, nVars);
1878  memset(nsVars, 0, sizeof(bdd_t *) * nVars);
1879  ns2ps = ALLOC(bdd_t *, nVars);
1880  memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
1881
1882  for (i = 0; i < array_n(nsVarBddArray); i++) {
1883    psVar = array_fetch(bdd_t *, psVarBddArray, i);
1884    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
1885    index = (int)bdd_top_var_id(nsVar);
1886    nsVars[index] = nsVar;
1887    ns2ps[index] = psVar;
1888  }
1889
1890  count = 0;
1891  for (i = 0; i < array_n(relationArray); i++) {
1892    relation = array_fetch(mdd_t *, relationArray, i);
1893    supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
1894    psVar = NULL;
1895    for (j = 0; j < array_n(supportBddIdArray); j++) {
1896      bddId = array_fetch(int, supportBddIdArray, j);
1897      psVar = ns2ps[bddId];
1898      if (psVar) {
1899        break;
1900      }
1901    }
1902    if (psVar) {
1903      if (count == 0)
1904        fprintf(fout, "CLUSTER[%d] {\n", count);
1905      else
1906        fprintf(fout, "\nCLUSTER[%d] {\n", count);
1907      count++;
1908    }
1909    for (j = 0; j < array_n(supportBddIdArray); j++) {
1910      bddId = array_fetch(int, supportBddIdArray, j);
1911      psVar = ns2ps[bddId];
1912      if (psVar) {
1913        name = mdd_read_var_name(psVar);
1914        nsVar = nsVars[bddId];
1915        mddId = mdd_read_mdd_id(nsVar);
1916        bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
1917        for (k = 0; k < array_n(bddIdArray); k++) {
1918          id = array_fetch(int, bddIdArray, k);
1919          if (id == bddId) {
1920            fprintf(fout, "%s %d\n", name, k);
1921            break;
1922          }
1923        }
1924        array_free(bddIdArray);
1925      }
1926    }
1927    array_free(supportBddIdArray);
1928    fprintf(fout, "}\n");
1929  }
1930
1931  FREE(nsVars);
1932  FREE(ns2ps);
1933}
1934
1935
1936
1937
1938/**Function********************************************************************
1939
1940  Synopsis    [Reads cluster file.]
1941
1942  Description [Reads cluster file.]
1943
1944  SideEffects []
1945
1946******************************************************************************/
1947void
1948ImgMlpReadClusterFile(FILE *fin, mdd_manager *mddManager,
1949                        ImgFunctionData_t *functionData,
1950                        array_t *relationArray,
1951                        array_t *psVarBddArray,
1952                        array_t *nsVarBddArray,
1953                        array_t *quantifyVarBddArray,
1954                        Img_DirectionType direction,
1955                        array_t **clusteredRelationArrayPtr,
1956                        array_t **arraySmoothVarBddArrayPtr,
1957                        ImgTrmOption_t *option)
1958{
1959  array_t       *clusteredRelationArray, *newRelationArray;
1960  array_t       *arraySmoothVarBddArray;
1961  int           i, j, k, nVars;
1962  long          bddId;
1963  int           mddId, id, index;
1964  mdd_t         *relation, *cluster, *newCluster;
1965  mdd_t         *var, *psVar, *nsVar, **nsVars, **ns2ps;
1966  array_t       *supportBddIdArray, *bddIdArray;
1967  char          *name;
1968  LatchList_t   **latchList;
1969  st_table      *intermediateTable, *nameTable, *quantifyVarsTable, *idTable;
1970  int           nRelVars, relBddId, relMddId;
1971  mdd_t         *relVar;
1972  char          *resolved;
1973  char          line[512], nameArray[512];
1974  st_generator  *stGen1, *stGen2;
1975
1976  nVars = bdd_num_vars(mddManager);
1977  nsVars = ALLOC(bdd_t *, nVars);
1978  memset(nsVars, 0, sizeof(bdd_t *) * nVars);
1979  ns2ps = ALLOC(bdd_t *, nVars);
1980  memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
1981  latchList = ALLOC(LatchList_t *, nVars);
1982  memset(latchList, 0, sizeof(LatchList_t *) * nVars);
1983  resolved = ALLOC(char, nVars);
1984  memset(resolved, 0, sizeof(char) * nVars);
1985
1986  quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
1987  for (i = 0; i < array_n(functionData->quantifyBddVars); i++) {
1988    var = array_fetch(mdd_t *, functionData->quantifyBddVars, i);
1989    index = (int)bdd_top_var_id(var);
1990    st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
1991  }
1992
1993  nameTable = st_init_table(strcmp, st_strhash);
1994  for (i = 0; i < array_n(nsVarBddArray); i++) {
1995    psVar = array_fetch(bdd_t *, psVarBddArray, i);
1996    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
1997    index = (int)bdd_top_var_id(nsVar);
1998    nsVars[index] = nsVar;
1999    ns2ps[index] = psVar;
2000    name = mdd_read_var_name(psVar);
2001    mddId = mdd_read_mdd_id(nsVar);
2002    st_insert(nameTable, name, (char *)(long)mddId);
2003
2004    index = (int)bdd_top_var_id(psVar);
2005    st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
2006  }
2007
2008  i = 0;
2009  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
2010    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
2011    i++;
2012  }
2013
2014  intermediateTable = st_init_table(st_ptrcmp, st_ptrhash);
2015  for (i = 0; i < array_n(relationArray); i++) {
2016    relation = array_fetch(mdd_t *, relationArray, i);
2017    supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
2018    nRelVars = 0;
2019    psVar = NIL(bdd_t);
2020    nsVar = NIL(bdd_t);
2021    relVar = NIL(bdd_t);
2022    relBddId = -1;
2023    relMddId = -1;
2024    idTable = st_init_table(st_numcmp, st_numhash);
2025    for (j = 0; j < array_n(supportBddIdArray); j++) {
2026      bddId = (long) array_fetch(int, supportBddIdArray, j);
2027      if (st_lookup(quantifyVarsTable, (char *)bddId, NIL(char *)))
2028        continue;
2029      psVar = ns2ps[bddId];
2030      if (psVar) {
2031        if (relVar) {
2032          bdd_free(relVar);
2033          relVar = NIL(bdd_t);
2034        }
2035        nsVar = nsVars[bddId];
2036        relMddId = mdd_read_mdd_id(nsVar);
2037        relBddId = (int) bddId;
2038        break;
2039      } else {
2040        if (nRelVars > 0) {
2041          if (relVar)
2042            bdd_free(relVar);
2043        }
2044        relVar = bdd_var_with_index(mddManager, (int) bddId);
2045        relMddId = mdd_read_mdd_id(relVar);
2046        relBddId = (int) bddId;
2047        name = mdd_read_var_name(relVar);
2048        st_insert(nameTable, name, (char *)(long)relMddId);
2049        st_insert(idTable, (char *)bddId, NIL(char));
2050        if (nRelVars >= 1) {
2051          bdd_free(relVar);
2052          relVar = NIL(bdd_t);
2053        }
2054        nRelVars++;
2055      }
2056    }
2057    array_free(supportBddIdArray);
2058    if (nsVar || relVar) {
2059      bddId = (int) relBddId;
2060      mddId = relMddId;
2061
2062      if (relVar)
2063        resolved[bddId] = 1;
2064
2065      bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
2066      for (k = 0; k < array_n(bddIdArray); k++) {
2067        id = array_fetch(int, bddIdArray, k);
2068        if (id == bddId) {
2069          if (latchList[mddId]) {
2070            if (latchList[mddId]->number == 1) {
2071              latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
2072              st_insert(latchList[mddId]->table,
2073                        (char *)(long)latchList[mddId]->bddId,
2074                        (char *)latchList[mddId]->relation);
2075            }
2076            st_insert(latchList[mddId]->table, (char *)bddId,
2077                      (char *)relation);
2078          } else {
2079            latchList[mddId] = ALLOC(LatchList_t, 1);
2080            latchList[mddId]->bddId = (int) bddId;
2081            latchList[mddId]->relation = relation;
2082            latchList[mddId]->number = 1;
2083            latchList[mddId]->table = NIL(st_table);
2084          }
2085          break;
2086        }
2087      }
2088      array_free(bddIdArray);
2089      st_free_table(idTable);
2090    } else {
2091      st_insert(intermediateTable, (char *)relation, (char *)idTable);
2092    }
2093  }
2094
2095  i = 0;
2096  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
2097    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
2098    i++;
2099  }
2100
2101  while (intermediateTable->num_entries > 0) {
2102    st_foreach_item(intermediateTable, stGen1, &relation, &idTable) {
2103      st_foreach_item(idTable, stGen2, &bddId, NIL(char *)) {
2104        if (resolved[bddId])
2105          st_delete(idTable, &bddId, NIL(char *));
2106      }
2107      if (idTable->num_entries == 1) {
2108        st_foreach_item(idTable, stGen2, &bddId, NULL);
2109        relVar = bdd_var_with_index(mddManager, (int) bddId);
2110        mddId = mdd_read_mdd_id(relVar);
2111        mdd_free(relVar);
2112
2113        st_delete(intermediateTable, &relation, NULL);
2114
2115        bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
2116        for (k = 0; k < array_n(bddIdArray); k++) {
2117          id = array_fetch(int, bddIdArray, k);
2118          if (id == bddId) {
2119            if (latchList[mddId]) {
2120              if (latchList[mddId]->number == 1) {
2121                latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
2122                st_insert(latchList[mddId]->table,
2123                          (char *)(long)latchList[mddId]->bddId,
2124                          (char *)latchList[mddId]->relation);
2125              }
2126              st_insert(latchList[mddId]->table, (char *)bddId,
2127                        (char *)relation);
2128            } else {
2129              latchList[mddId] = ALLOC(LatchList_t, 1);
2130              latchList[mddId]->bddId = (int) bddId;
2131              latchList[mddId]->relation = relation;
2132              latchList[mddId]->number = 1;
2133              latchList[mddId]->table = NIL(st_table);
2134            }
2135            break;
2136          }
2137        }
2138        array_free(bddIdArray);
2139      }
2140    }
2141  }
2142  st_free_table(intermediateTable);
2143
2144  i = 0;
2145  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
2146    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
2147    i++;
2148  }
2149
2150  cluster = NIL(mdd_t);
2151  clusteredRelationArray = array_alloc(mdd_t *, 0);
2152  while (fgets(line, 512, fin)) {
2153    if (line[0] == '\n' || line[0] == '#')
2154      continue;
2155    if (strncmp(line, "CLUSTER", 7) == 0)
2156      cluster = mdd_one(mddManager);
2157    else if (strncmp(line, "}", 1) == 0)
2158      array_insert_last(mdd_t *, clusteredRelationArray, cluster);
2159    else {
2160      sscanf(line, "%s %d", nameArray, &id);
2161      if (st_lookup_int(nameTable, nameArray, &mddId) == 0)
2162        assert(0);
2163      if (latchList[mddId]) {
2164        if (latchList[mddId]->table) {
2165          bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
2166          assert(id < array_n(bddIdArray));
2167          bddId = (long) array_fetch(int, bddIdArray, id);
2168          if (st_lookup(latchList[mddId]->table, (char *)bddId, &relation)) {
2169            latchList[mddId]->number--;
2170            if (latchList[mddId]->number == 0) {
2171              st_free_table(latchList[mddId]->table);
2172              FREE(latchList[mddId]);
2173              latchList[mddId] = NIL(LatchList_t);
2174            }
2175          } else
2176            assert(0);
2177        } else {
2178          relation = latchList[mddId]->relation;
2179          FREE(latchList[mddId]);
2180          latchList[mddId] = NIL(LatchList_t);
2181        }
2182        newCluster = bdd_and(cluster, relation, 1, 1);
2183        mdd_free(cluster);
2184        cluster = newCluster;
2185      } else
2186        assert(0);
2187    }
2188  }
2189
2190  for (i = 0; i < nVars; i++) {
2191    if (latchList[i]) {
2192      if (latchList[i]->table) {
2193        st_foreach_item(latchList[i]->table, stGen1, &bddId, &relation) {
2194          cluster = bdd_dup(relation);
2195          array_insert_last(mdd_t *, clusteredRelationArray, cluster);
2196        }
2197        st_free_table(latchList[i]->table);
2198      } else {
2199        cluster = bdd_dup(latchList[i]->relation);
2200        array_insert_last(mdd_t *, clusteredRelationArray, cluster);
2201      }
2202      FREE(latchList[i]);
2203    }
2204  }
2205
2206  FREE(nsVars);
2207  FREE(ns2ps);
2208  FREE(resolved);
2209  FREE(latchList);
2210
2211  st_free_table(nameTable);
2212  st_free_table(quantifyVarsTable);
2213
2214  if (arraySmoothVarBddArrayPtr) {
2215    ImgMlpGetQuantificationSchedule(mddManager,
2216                clusteredRelationArray, psVarBddArray, quantifyVarBddArray,
2217                nsVarBddArray, &newRelationArray, &arraySmoothVarBddArray,
2218                direction, option);
2219    mdd_array_free(clusteredRelationArray);
2220    clusteredRelationArray = newRelationArray;
2221  } else
2222    arraySmoothVarBddArray = NIL(array_t);
2223
2224  *clusteredRelationArrayPtr = clusteredRelationArray;
2225  *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
2226}
2227
2228
2229/*---------------------------------------------------------------------------*/
2230/* Definition of static functions                                            */
2231/*---------------------------------------------------------------------------*/
2232
2233/**Function********************************************************************
2234
2235  Synopsis    [Setups MLP.]
2236
2237  Description [Setups MLP.]
2238
2239  SideEffects []
2240
2241******************************************************************************/
2242static void
2243SetupMlp(mdd_manager *mddManager,
2244         char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
2245         RcInfo_t *rowInfo, RcInfo_t *colInfo, int *varPos,
2246         array_t *nsVarBddArray, int *nActiveRows, int *nActiveCols,
2247         array_t *nonAppearingVarBddArray,
2248         Img_DirectionType direction, ImgTrmOption_t *option)
2249{
2250  int           i, j, x, y, s, t;
2251  int           row, col, otherCol, nr, nc, index;
2252  long          initialTime, finalTime;
2253  bdd_t         *relation, *nsVar;
2254  array_t       *supportArray, *localVarBddArray;
2255  int           support;
2256  array_t       **arrayLocalVarBddArray;
2257  float         lambda1, lambda2, lambda3;
2258  bdd_t         **nsVarArray;
2259  int           nVars;
2260
2261  if (option->mlpVerbosity >= 2)
2262    initialTime = util_cpu_time();
2263  else
2264    initialTime = 0;
2265
2266  nVars = bdd_num_vars(mddManager);
2267  nsVarArray = ALLOC(bdd_t *, nVars);
2268  memset(nsVarArray, 0, sizeof(bdd_t *) * nVars);
2269  for (i = 0; i < array_n(nsVarBddArray); i++) {
2270    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
2271    index = (int)bdd_top_var_id(nsVar);
2272    nsVarArray[index] = nsVar;
2273  }
2274
2275  for (i = 0; i < nRows; i++) {
2276    relation = rowInfo[i].data.row.func;
2277    rowInfo[i].data.row.nsVarBddArray = array_alloc(bdd_t *, 0);
2278    supportArray = mdd_get_bdd_support_ids(mddManager, relation);
2279    for (j = 0; j < array_n(supportArray); j++) {
2280      support = array_fetch(int, supportArray, j);
2281      nsVar = nsVarArray[support];
2282      if (nsVar) {
2283        array_insert_last(bdd_t *, rowInfo[i].data.row.nsVarBddArray, nsVar);
2284        if (varPos[support])
2285          xy[i][varPos[support]] = 1;
2286        else {
2287          index = (int)bdd_top_var_id(colInfo[0].data.col.var);
2288          if (index == support)
2289            xy[i][varPos[support]] = 1;
2290        }
2291      } else
2292        xy[i][varPos[support]] = 1;
2293    }
2294    array_free(supportArray);
2295  }
2296  FREE(nsVarArray);
2297
2298  for (x = 0; x < nRows; x++) {
2299    rowInfo[x].gMin = nCols;
2300    rowInfo[x].gMax = -1;
2301    rowInfo[x].pos = x;
2302    rowInfo[x].prevG = -1;
2303    rowInfo[x].nextG = nCols;
2304  }
2305  for (y = 0; y < nCols; y++) {
2306    colInfo[y].gMin = nRows;
2307    colInfo[y].gMax = -1;
2308    colInfo[y].pos = y;
2309    colInfo[y].prevG = -1;
2310    colInfo[y].nextG = nRows;
2311  }
2312
2313  for (x = 0; x < nRows; x++) {
2314    for (y = 0; y < nCols; y++) {
2315      if (xy[x][y]) {
2316        if (x < colInfo[y].gMin)
2317          colInfo[y].gMin = x;
2318        if (x > colInfo[y].gMax)
2319          colInfo[y].gMax = x;
2320        if (y < rowInfo[x].gMin)
2321          rowInfo[x].gMin = y;
2322        if (y > rowInfo[x].gMax)
2323          rowInfo[x].gMax = y;
2324        rowInfo[x].gNum++;
2325        colInfo[y].gNum++;
2326      }
2327    }
2328  }
2329
2330  nc = nCols;
2331  arrayLocalVarBddArray = ALLOC(array_t *, nRows);
2332  memset(arrayLocalVarBddArray, 0, sizeof(array_t *) * nRows);
2333  for (y = 0; y < nc; y++) {
2334    col = colOrder[y];
2335    if (colInfo[col].data.col.type == 2 && colInfo[col].gNum == 1) {
2336      row = colInfo[col].gMin;
2337      rowInfo[row].gNum--;
2338      if (rowInfo[row].gNum == 1) {
2339        if (rowInfo[row].gMin == col) {
2340          rowInfo[row].gMin = rowInfo[row].gMax;
2341          rowInfo[row].lMin = rowInfo[row].lMax;
2342        } else {
2343          rowInfo[row].gMax = rowInfo[row].gMin;
2344          rowInfo[row].lMax = rowInfo[row].lMin;
2345        }
2346      } else if (rowInfo[row].gNum > 1) {
2347        if (rowInfo[row].gMin == col) {
2348          s = colInfo[rowInfo[row].gMin].pos;
2349          t = colInfo[rowInfo[row].gMax].pos;
2350          for (j = s + 1; j <= t; j++) {
2351            otherCol = colOrder[j];
2352            if (xy[row][otherCol]) {
2353              rowInfo[row].gMin = otherCol;
2354              rowInfo[row].lMin = otherCol;
2355              break;
2356            }
2357          }
2358        } else if (rowInfo[row].gMax == col) {
2359          s = colInfo[rowInfo[row].gMin].pos;
2360          t = colInfo[rowInfo[row].gMax].pos;
2361          for (j = t - 1; j >= s; j--) {
2362            otherCol = colOrder[j];
2363            if (xy[row][otherCol]) {
2364              rowInfo[row].gMax = otherCol;
2365              rowInfo[row].lMax = otherCol;
2366              break;
2367            }
2368          }
2369        }
2370      }
2371
2372      for (j = y; j < nc - 1; j++) {
2373        colOrder[j] = colOrder[j + 1];
2374        colInfo[colOrder[j]].pos = j;
2375      }
2376      colOrder[nc - 1] = col;
2377      colInfo[col].pos = nc - 1;
2378
2379      nc--;
2380      y--;
2381
2382      if (!arrayLocalVarBddArray[row])
2383        arrayLocalVarBddArray[row] = array_alloc(bdd_t *, 0);
2384      array_insert_last(bdd_t *, arrayLocalVarBddArray[row],
2385                        colInfo[col].data.col.var);
2386    }
2387  }
2388
2389  if (direction == Img_Backward_c) {
2390    long        lindex;
2391    st_table    *unusedNsTable;
2392    st_generator *gen;
2393
2394    unusedNsTable = st_init_table(st_numcmp, st_numhash);
2395    for (i = 0; i < array_n(nsVarBddArray); i++) {
2396      nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
2397      lindex = (long) bdd_top_var_id(nsVar);
2398      st_insert(unusedNsTable, (char *)lindex, (char *)nsVar);
2399    }
2400    for (i = 0; i < nRows; i++) {
2401      for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
2402        nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
2403        lindex = (long) bdd_top_var_id(nsVar);
2404        st_delete(unusedNsTable, &lindex, NULL);
2405      }
2406    }
2407    st_foreach_item(unusedNsTable, gen, &lindex, &nsVar) {
2408      array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
2409    }
2410    st_free_table(unusedNsTable);
2411  }
2412
2413  for (i = 0; i < nRows; i++) {
2414    localVarBddArray = arrayLocalVarBddArray[i];
2415    if (localVarBddArray) {
2416      relation = bdd_smooth(rowInfo[i].data.row.func, localVarBddArray);
2417      if (nonAppearingVarBddArray && direction == Img_Backward_c &&
2418          bdd_is_tautology(relation, 1)) {
2419          for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
2420            nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
2421            array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
2422          }
2423      }
2424      bdd_free(rowInfo[i].data.row.func);
2425      rowInfo[i].data.row.func = relation;
2426      UpdateDisapearingPsVars(mddManager, xy, nRows, nCols,
2427                        rowOrder, colOrder, rowInfo, colInfo,
2428                        i, option);
2429      if (localVarBddArray)
2430        array_free(localVarBddArray);
2431    }
2432  }
2433  FREE(arrayLocalVarBddArray);
2434
2435  for (y = 0; y < nc; y++) {
2436    col = colOrder[y];
2437    if (colInfo[col].gNum == 0) {
2438      if (nonAppearingVarBddArray &&
2439          direction == Img_Forward_c && colInfo[col].data.col.type == 1) {
2440        array_insert_last(bdd_t *, nonAppearingVarBddArray,
2441                          bdd_dup(colInfo[col].data.col.var));
2442      }
2443      for (j = y; j < nc - 1; j++) {
2444        colOrder[j] = colOrder[j + 1];
2445        colInfo[colOrder[j]].pos = j;
2446      }
2447      colOrder[nc - 1] = col;
2448      colInfo[col].pos = nc - 1;
2449      nc--;
2450      y--;
2451    }
2452  }
2453
2454  nr = nRows;
2455  for (x = 0; x < nr; x++) {
2456    row = rowOrder[x];
2457    if (rowInfo[row].gNum == 0) {
2458      for (i = x; i < nr - 1; i++) {
2459        rowOrder[i] = rowOrder[i + 1];
2460        rowInfo[rowOrder[i]].pos = i;
2461      }
2462      rowOrder[nr - 1] = row;
2463      rowInfo[row].pos = nr - 1;
2464      nr--;
2465      x--;
2466    }
2467  }
2468
2469  for (x = 0; x < nr; x++) {
2470    row = rowOrder[x];
2471    rowInfo[row].lMin = rowInfo[row].gMin;
2472    rowInfo[row].lMax = rowInfo[row].gMax;
2473    rowInfo[row].lNum = rowInfo[row].gNum;
2474    if (nc != nCols && rowInfo[row].nextG == nCols)
2475      rowInfo[row].nextG = nc;
2476  }
2477  for (y = 0; y < nc; y++) {
2478    col = colOrder[y];
2479    colInfo[col].lMin = colInfo[col].gMin;
2480    colInfo[col].lMax = colInfo[col].gMax;
2481    colInfo[col].lNum = colInfo[col].gNum;
2482    if (nr != nRows && colInfo[col].nextG == nRows)
2483      colInfo[col].nextG = nr;
2484  }
2485  if (option->mlpVerbosity >= 2) {
2486    finalTime = util_cpu_time();
2487    fprintf(vis_stdout, "time for setup = %10g\n",
2488           (double)(finalTime - initialTime) / 1000.0);
2489
2490    lambda1 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
2491                                rowOrder, colOrder, direction, 0, 0, option);
2492    lambda2 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
2493                                rowOrder, colOrder, direction, 1, 0, option);
2494    lambda3 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
2495                                rowOrder, colOrder, direction, 2, 0, option);
2496    fprintf(vis_stdout, "Initial Lambda = %f (%f, %f)\n",
2497            lambda1, lambda2, lambda3);
2498  }
2499
2500  if (option->mlpDebug) {
2501    CheckMatrix(xy, NIL(SccList_t), nr, nc, rowInfo, colInfo,
2502                rowOrder, colOrder, 0, nr - 1, 0, nc - 1, 1);
2503  }
2504
2505  *nActiveRows = nr;
2506  *nActiveCols = nc;
2507}
2508
2509
2510/**Function********************************************************************
2511
2512  Synopsis    [Performs connected component decomposition.]
2513
2514  Description [Performs connected component decomposition.]
2515
2516  SideEffects []
2517
2518******************************************************************************/
2519static SccList_t *
2520MlpDecomposeScc(mdd_manager *mddManager, char **xy, int nRows,
2521                int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder,
2522                RcInfo_t *rowInfo, RcInfo_t *colInfo,
2523                int clusteredFlag, ImgTrmOption_t *option)
2524{
2525  int           i, j, x, y, size, nVars;
2526  int           startRow, startCol;
2527  int           nGroups, nChosen;
2528  int           row, col, otherRow;
2529  int           s1, t1, s2, t2;
2530  char          *rowFlag, *colFlag, *stackFlag;
2531  int           *stack;
2532  SccList_t     *sccHeadList, *sccTailList, *sccList;
2533  array_t       *rowScc, *colScc, *sccArray;
2534  long          initialTime, finalTime;
2535  int           *newRowOrder, *newColOrder;
2536  int           nCurRows, nCurCols;
2537
2538  if (!option->mlpDecomposeScc) {
2539    sccList = ALLOC(SccList_t, 1);
2540    sccList->nFuncs = nActiveRows;
2541    sccList->nVars = nActiveCols;
2542    sccList->startFunc = 0;
2543    sccList->lastFunc = nActiveRows - 1;
2544    sccList->startVar = 0;
2545    sccList->lastVar = nActiveCols - 1;
2546    sccList->next = NIL(SccList_t);
2547    return(sccList);
2548  }
2549
2550  if (option->mlpVerbosity >= 2)
2551    initialTime = util_cpu_time();
2552  else
2553    initialTime = 0;
2554
2555  sccHeadList = NIL(SccList_t);
2556  sccTailList = NIL(SccList_t);
2557
2558  rowFlag = ALLOC(char, nRows);
2559  memset(rowFlag, 0, sizeof(char) * nRows);
2560  nVars = bdd_num_vars(mddManager);
2561  colFlag = ALLOC(char, nVars);
2562  memset(colFlag, 0, sizeof(char) * nVars);
2563  stack = ALLOC(int, nActiveRows);
2564  stackFlag = ALLOC(char, nRows);
2565  memset(stackFlag, 0, sizeof(char) * nRows);
2566
2567  startRow = 0;
2568  startCol = 0;
2569  nGroups = 0;
2570  nChosen = 0;
2571  while (nChosen < nActiveRows) {
2572    rowScc = array_alloc(int, 0);
2573    colScc = array_alloc(int, 0);
2574
2575    size = 0;
2576    for (i = startRow; i < nActiveRows; i++) {
2577      row = rowOrder[i];
2578      if (rowFlag[row] == 0) {
2579        stack[0] = row;
2580        size = 1;
2581        stackFlag[row] = 1;
2582        break;
2583      }
2584    }
2585
2586    while (size) {
2587      if (size + array_n(rowScc) == nRows) {
2588        FREE(stack);
2589        FREE(stackFlag);
2590        FREE(rowFlag);
2591        FREE(colFlag);
2592        array_free(rowScc);
2593        array_free(colScc);
2594
2595        sccList = ALLOC(SccList_t, 1);
2596        sccList->nFuncs = nActiveRows;
2597        sccList->nVars = nActiveCols;
2598        sccList->startFunc = 0;
2599        sccList->lastFunc = nActiveRows - 1;
2600        sccList->startVar = 0;
2601        sccList->lastVar = nActiveCols - 1;
2602        sccList->next = NIL(SccList_t);
2603        return(sccList);
2604      }
2605
2606      size--;
2607      row = stack[size];
2608      x = rowInfo[row].pos;
2609      rowFlag[row] = nGroups + 1;
2610      array_insert_last(int, rowScc, x);
2611      nChosen++;
2612      s1 = colInfo[rowInfo[row].gMin].pos;
2613      t1 = colInfo[rowInfo[row].gMax].pos;
2614      for (y = s1; y <= t1; y++) {
2615        col = colOrder[y];
2616        if (colInfo[col].gNum == nRows) {
2617          FREE(stack);
2618          FREE(stackFlag);
2619          FREE(rowFlag);
2620          FREE(colFlag);
2621          array_free(rowScc);
2622          array_free(colScc);
2623
2624          sccList = ALLOC(SccList_t, 1);
2625          sccList->nFuncs = nActiveRows;
2626          sccList->nVars = nActiveCols;
2627          sccList->startFunc = 0;
2628          sccList->lastFunc = nActiveRows - 1;
2629          sccList->startVar = 0;
2630          sccList->lastVar = nActiveCols - 1;
2631          sccList->next = NIL(SccList_t);
2632          return(sccList);
2633        }
2634        if (!xy[row][col] || colFlag[col])
2635          continue;
2636        colFlag[col] = nGroups + 1;
2637        array_insert_last(int, colScc, y);
2638        s2 = rowInfo[colInfo[col].gMin].pos;
2639        t2 = rowInfo[colInfo[col].gMax].pos;
2640        for (i = s2; i <= t2; i++) {
2641          otherRow = rowOrder[i];
2642          if (rowFlag[otherRow] || stackFlag[otherRow])
2643            continue;
2644          if (xy[otherRow][col]) {
2645            stack[size] = otherRow;
2646            size++;
2647            stackFlag[otherRow] = 1;
2648          }
2649        }
2650      }
2651    }
2652
2653    nGroups++;
2654    if (nGroups == 1 && nChosen == nActiveRows) {
2655      sccList = ALLOC(SccList_t, 1);
2656      sccList->nFuncs = nActiveRows;
2657      sccList->nVars = nActiveCols;
2658      sccList->startFunc = 0;
2659      sccList->lastFunc = nActiveRows - 1;
2660      sccList->startVar = 0;
2661      sccList->lastVar = nActiveCols - 1;
2662      sccList->next = NIL(SccList_t);
2663
2664      sccHeadList = sccList;
2665
2666      array_free(rowScc);
2667      array_free(colScc);
2668      break;
2669    }
2670
2671    /* Move the rows and columns that belong to the current group to top-left */
2672    array_sort(rowScc, SccSortRc);
2673    array_sort(colScc, SccSortRc);
2674    for (i = 0; i < array_n(rowScc); i++) {
2675      x = array_fetch(int, rowScc, i);
2676      if (x == startRow + i)
2677        continue;
2678      row = rowOrder[x];
2679      for (j = x; j > startRow + i; j--) {
2680        rowOrder[j] = rowOrder[j - 1];
2681        rowInfo[rowOrder[j]].pos = j;
2682      }
2683      rowOrder[startRow + i] = row;
2684      rowInfo[row].pos = startRow + i;
2685    }
2686    for (i = 0; i < array_n(colScc); i++) {
2687      y = array_fetch(int, colScc, i);
2688      if (y == startCol + i)
2689        continue;
2690      col = colOrder[y];
2691      for (j = y; j > startCol + i; j--) {
2692        colOrder[j] = colOrder[j - 1];
2693        colInfo[colOrder[j]].pos = j;
2694      }
2695      colOrder[startCol + i] = col;
2696      colInfo[col].pos = startCol + i;
2697    }
2698
2699    sccList = ALLOC(SccList_t, 1);
2700    sccList->nFuncs = array_n(rowScc);
2701    sccList->nVars = array_n(colScc);
2702    sccList->startFunc = startRow;
2703    sccList->lastFunc = startRow + sccList->nFuncs - 1;
2704    sccList->startVar = startCol;
2705    sccList->lastVar = startCol + sccList->nVars - 1;
2706    sccList->next = NIL(SccList_t);
2707    startRow += sccList->nFuncs;
2708    startCol += sccList->nVars;
2709
2710    if (sccTailList)
2711      sccTailList->next = sccList;
2712    else
2713      sccHeadList = sccList;
2714    sccTailList = sccList;
2715
2716    array_free(rowScc);
2717    array_free(colScc);
2718
2719    if (option->mlpDebug) {
2720      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
2721                  rowInfo, colInfo, rowOrder, colOrder,
2722                  0, nActiveRows - 1, 0, nActiveCols - 1, 1);
2723    }
2724  }
2725
2726  FREE(stack);
2727  FREE(stackFlag);
2728  FREE(rowFlag);
2729  FREE(colFlag);
2730
2731  if (option->mlpSortScc && clusteredFlag == 0) {
2732    sccArray = array_alloc(SccList_t *, 0);
2733    sccList = sccHeadList;
2734    while (sccList) {
2735      array_insert_last(SccList_t *, sccArray, sccList);
2736      sccList = sccList->next;
2737    }
2738
2739    if (option->mlpSortSccMode == 0) {
2740      if (option->mlpSortScc == 1)
2741        array_sort(sccArray, SccSortListIncreasingWithArea);
2742      else
2743        array_sort(sccArray, SccSortListDecreasingWithArea);
2744    } else if (option->mlpSortSccMode == 1) {
2745      if (option->mlpSortScc == 1)
2746        array_sort(sccArray, SccSortListIncreasingWithVars);
2747      else
2748        array_sort(sccArray, SccSortListDecreasingWithVars);
2749    } else {
2750      if (option->mlpSortScc == 1)
2751        array_sort(sccArray, SccSortListIncreasingWithRatio);
2752      else
2753        array_sort(sccArray, SccSortListDecreasingWithRatio);
2754    }
2755
2756    newRowOrder = ALLOC(int, nActiveRows);
2757    newColOrder = ALLOC(int, nActiveCols);
2758
2759    nCurRows = 0;
2760    nCurCols = 0;
2761    sccHeadList = NIL(SccList_t);
2762    for (i = 0; i < array_n(sccArray); i++) {
2763      sccList = array_fetch(SccList_t *, sccArray, i);
2764      if (sccHeadList)
2765        sccTailList->next = sccList;
2766      else
2767        sccHeadList = sccList;
2768      sccTailList = sccList;
2769      sccList->next = NIL(SccList_t);
2770
2771      for (j = sccList->startFunc; j <= sccList->lastFunc; j++) {
2772        row = rowOrder[j];
2773        newRowOrder[nCurRows + j - sccList->startFunc] = rowOrder[j];
2774        rowInfo[row].pos = nCurRows + j - sccList->startFunc;
2775      }
2776      sccList->startFunc = nCurRows;
2777      sccList->lastFunc = nCurRows + sccList->nFuncs - 1;
2778      nCurRows += sccList->nFuncs;
2779
2780      for (j = sccList->startVar; j <= sccList->lastVar; j++) {
2781        col = colOrder[j];
2782        newColOrder[nCurCols + j - sccList->startVar] = colOrder[j];
2783        colInfo[col].pos = nCurCols + j - sccList->startVar;
2784      }
2785      sccList->startVar = nCurCols;
2786      sccList->lastVar = nCurCols + sccList->nVars - 1;
2787      nCurCols += sccList->nVars;
2788    }
2789
2790    memcpy(rowOrder, newRowOrder, sizeof(int) * nActiveRows);
2791    memcpy(colOrder, newColOrder, sizeof(int) * nActiveCols);
2792
2793    if (option->mlpDebug) {
2794      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
2795                  rowInfo, colInfo, rowOrder, colOrder,
2796                  0, nActiveRows - 1, 0, nActiveCols - 1, 1);
2797    }
2798
2799    FREE(newRowOrder);
2800    FREE(newColOrder);
2801    array_free(sccArray);
2802  }
2803
2804  if (option->mlpVerbosity >= 2) {
2805    finalTime = util_cpu_time();
2806    fprintf(vis_stdout, "time for scc decomposition = %10g (#scc=%d)\n",
2807            (double)(finalTime - initialTime) / 1000.0, nGroups);
2808  }
2809
2810  return(sccHeadList);
2811}
2812
2813
2814/**Function********************************************************************
2815
2816  Synopsis    [Sorts connected components with the number of variables.]
2817
2818  Description [Sorts connected components with the number of variables.]
2819
2820  SideEffects []
2821
2822******************************************************************************/
2823static int
2824SccSortListIncreasingWithVars(const void *p1, const void *p2)
2825{
2826  SccList_t **scc1 = (SccList_t **) p1;
2827  SccList_t **scc2 = (SccList_t **) p2;
2828  if ((*scc1)->nVars > (*scc2)->nVars)
2829    return(1);
2830  else if ((*scc1)->nVars < (*scc2)->nVars)
2831    return(-1);
2832  else
2833    return(0);
2834}
2835
2836
2837/**Function********************************************************************
2838
2839  Synopsis    [Sorts connected components with the number of variables.]
2840
2841  Description [Sorts connected components with the number of variables.]
2842
2843  SideEffects []
2844
2845******************************************************************************/
2846static int
2847SccSortListDecreasingWithVars(const void *p1, const void *p2)
2848{
2849  SccList_t **scc1 = (SccList_t **) p1;
2850  SccList_t **scc2 = (SccList_t **) p2;
2851  if ((*scc1)->nVars < (*scc2)->nVars)
2852    return(1);
2853  else if ((*scc1)->nVars > (*scc2)->nVars)
2854    return(-1);
2855  else
2856    return(0);
2857}
2858
2859
2860/**Function********************************************************************
2861
2862  Synopsis    [Sorts connected components with area.]
2863
2864  Description [Sorts connected components with area.]
2865
2866  SideEffects []
2867
2868******************************************************************************/
2869static int
2870SccSortListIncreasingWithArea(const void *p1, const void *p2)
2871{
2872  SccList_t **scc1 = (SccList_t **) p1;
2873  SccList_t **scc2 = (SccList_t **) p2;
2874  int   area1, area2;
2875
2876  area1 = (*scc1)->nFuncs * (*scc1)->nVars;
2877  area2 = (*scc2)->nFuncs * (*scc2)->nVars;
2878  if (area1 > area2)
2879    return(1);
2880  else if (area1 < area2)
2881    return(-1);
2882  else
2883    return(0);
2884}
2885
2886
2887/**Function********************************************************************
2888
2889  Synopsis    [Sorts connected components with area.]
2890
2891  Description [Sorts connected components with area.]
2892
2893  SideEffects []
2894
2895******************************************************************************/
2896static int
2897SccSortListDecreasingWithArea(const void *p1, const void *p2)
2898{
2899  SccList_t **scc1 = (SccList_t **) p1;
2900  SccList_t **scc2 = (SccList_t **) p2;
2901  int   area1, area2;
2902
2903  area1 = (*scc1)->nFuncs * (*scc1)->nVars;
2904  area2 = (*scc2)->nFuncs * (*scc2)->nVars;
2905  if (area1 < area2)
2906    return(1);
2907  else if (area1 > area2)
2908    return(-1);
2909  else
2910    return(0);
2911}
2912
2913
2914/**Function********************************************************************
2915
2916  Synopsis    [Sorts connected components with aspect ratio.]
2917
2918  Description [Sorts connected components with aspect ratio.]
2919
2920  SideEffects []
2921
2922******************************************************************************/
2923static int
2924SccSortListIncreasingWithRatio(const void *p1, const void *p2)
2925{
2926  SccList_t **scc1 = (SccList_t **) p1;
2927  SccList_t **scc2 = (SccList_t **) p2;
2928  float ratio1, ratio2;
2929
2930  ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
2931  ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
2932  if (ratio1 > ratio2)
2933    return(1);
2934  else if (ratio1 < ratio2)
2935    return(-1);
2936  else
2937    return(0);
2938}
2939
2940
2941/**Function********************************************************************
2942
2943  Synopsis    [Sorts connected components with aspect ratio.]
2944
2945  Description [Sorts connected components with aspect ratio.]
2946
2947  SideEffects []
2948
2949******************************************************************************/
2950static int
2951SccSortListDecreasingWithRatio(const void *p1, const void *p2)
2952{
2953  SccList_t **scc1 = (SccList_t **) p1;
2954  SccList_t **scc2 = (SccList_t **) p2;
2955  float ratio1, ratio2;
2956
2957  ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
2958  ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
2959  if (ratio1 < ratio2)
2960    return(1);
2961  else if (ratio1 > ratio2)
2962    return(-1);
2963  else
2964    return(0);
2965}
2966
2967
2968/**Function********************************************************************
2969
2970  Synopsis    [Sorts rows or columns using connected component index.]
2971
2972  Description [Sorts rows or columns using connected component index.]
2973
2974  SideEffects []
2975
2976******************************************************************************/
2977static int
2978SccSortRc(const void * p1, const void * p2)
2979{
2980  int *n1 = (int *) p1;
2981  int *n2 = (int *) p2;
2982  if (*n1 > *n2)
2983    return(1);
2984  else if (*n1 < *n2)
2985    return(-1);
2986  else
2987    return(0);
2988}
2989
2990
2991/**Function********************************************************************
2992
2993  Synopsis    [Frees list of connected components.]
2994
2995  Description [Frees list of connected components.]
2996
2997  SideEffects []
2998
2999******************************************************************************/
3000static void
3001FreeSccList(SccList_t *sccHeadList)
3002{
3003  SccList_t     *sccList, *sccNextList;
3004
3005  sccList = sccHeadList;
3006  while (sccList) {
3007    sccNextList = sccList->next;
3008    FREE(sccList);
3009    sccList = sccNextList;
3010  }
3011}
3012
3013
3014/**Function********************************************************************
3015
3016  Synopsis    [Returns the number of connected components in the list.]
3017
3018  Description [Returns the number of connected components in the list.]
3019
3020  SideEffects []
3021
3022******************************************************************************/
3023static int
3024NumOfSccs(SccList_t *sccHeadList)
3025{
3026  SccList_t     *sccList;
3027  int           num = 0;
3028
3029  sccList = sccHeadList;
3030  while (sccList) {
3031    num++;
3032    sccList = sccList->next;
3033  }
3034  return(num);
3035}
3036
3037
3038/**Function********************************************************************
3039
3040  Synopsis    [Makes dependence matrix block lower triangle.]
3041
3042  Description [Makes dependence matrix block lower triangle by pivoting
3043  rows and columns.]
3044
3045  SideEffects []
3046
3047******************************************************************************/
3048static void
3049BlockLowerTriangle(char **xy, int nRows, int nCols,
3050                   int nActiveRows, int nActiveCols,
3051                   SccList_t *sccList, int *rowOrder, int *colOrder,
3052                   RcInfo_t *rowInfo, RcInfo_t *colInfo,
3053                   ImgTrmOption_t *option)
3054{
3055  long          initialTime, finalTime;
3056  int           startFunc, lastFunc, startVar, lastVar;
3057  int           nLeftRows, nLeftCols;
3058  int           saveStartFunc, saveLastFunc;
3059  int           saveStartVar, saveLastVar;
3060
3061  if (sccList) {
3062    if (sccList->nFuncs == 1 || sccList->nVars == 1)
3063      return;
3064    startFunc = sccList->startFunc;
3065    lastFunc = sccList->lastFunc;
3066    startVar = sccList->startVar;
3067    lastVar = sccList->lastVar;
3068  } else {
3069    startFunc = 0;
3070    lastFunc = nActiveRows - 1;
3071    startVar = 0;
3072    lastVar = nActiveCols - 1;
3073  }
3074
3075  if (option->mlpVerbosity >= 2) {
3076    saveStartFunc = startFunc;
3077    saveLastFunc = lastFunc;
3078    saveStartVar = startVar;
3079    saveLastVar = lastVar;
3080  } else {
3081    /* To remove compiler warnings */
3082    saveStartFunc = 0;
3083    saveLastFunc = 0;
3084    saveStartVar = 0;
3085    saveLastVar = 0;
3086  }
3087
3088  if (option->mlpDebug) {
3089    CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
3090                rowOrder, colOrder, startFunc, lastFunc, startVar, lastVar, 1);
3091  }
3092
3093  if (option->mlpCsFirst) {
3094    /*
3095     * Find singleton columns and move each column to the right of the active
3096     * window and move its row to the bottom of the active window.
3097     */
3098    if (option->mlpSkipCs == 0) {
3099      if (option->mlpVerbosity >= 2)
3100        initialTime = util_cpu_time();
3101      else /* to remove uninitialized variables warning */
3102        initialTime = 0;
3103      FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
3104                               &startFunc, &lastFunc, &startVar, &lastVar,
3105                               rowInfo, colInfo, rowOrder, colOrder, option);
3106      if (option->mlpVerbosity >= 2) {
3107        finalTime = util_cpu_time();
3108        fprintf(vis_stdout,
3109                "time for col singleton = %10g (#row=%d, #col=%d)\n",
3110                (double)(finalTime - initialTime) / 1000.0,
3111                saveLastFunc - lastFunc, saveLastVar - lastVar);
3112      }
3113    }
3114
3115    /*
3116     * Find singleton rows and move each row to the top of the active window
3117     * and move its column to the left of the active window.
3118     */
3119    if (option->mlpSkipRs == 0) {
3120      if (option->mlpVerbosity >= 2)
3121        initialTime = util_cpu_time();
3122      else /* to remove uninitialized variables warning */
3123        initialTime = 0;
3124      FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
3125                               &startFunc, &lastFunc, &startVar, &lastVar,
3126                               rowInfo, colInfo, rowOrder, colOrder, option);
3127      if (option->mlpVerbosity >= 2) {
3128        finalTime = util_cpu_time();
3129        fprintf(vis_stdout,
3130                "time for row singleton = %10g (#row=%d, #col=%d)\n",
3131                (double)(finalTime - initialTime) / 1000.0,
3132                startFunc - saveStartFunc, startVar - saveStartVar);
3133      }
3134    }
3135  } else {
3136    /*
3137     * Find singleton rows and move each row to the top of the active window
3138     * and move its column to the left of the active window.
3139     */
3140    if (option->mlpSkipRs == 0) {
3141      if (option->mlpVerbosity >= 2)
3142        initialTime = util_cpu_time();
3143      else /* to remove uninitialized variables warning */
3144        initialTime = 0;
3145      FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
3146                               &startFunc, &lastFunc, &startVar, &lastVar,
3147                               rowInfo, colInfo, rowOrder, colOrder, option);
3148      if (option->mlpVerbosity >= 2) {
3149        finalTime = util_cpu_time();
3150        fprintf(vis_stdout,
3151                "time for row singleton = %10g (#row=%d, #col=%d)\n",
3152                (double)(finalTime - initialTime) / 1000.0,
3153                startFunc - saveStartFunc, startVar - saveStartVar);
3154      }
3155    }
3156
3157    /*
3158     * Find singleton columns and move each column to the right of the active
3159     * window and move its row to the bottom of the active window.
3160     */
3161    if (option->mlpSkipCs == 0) {
3162      if (option->mlpVerbosity >= 2)
3163        initialTime = util_cpu_time();
3164      else /* to remove uninitialized variables warning */
3165        initialTime = 0;
3166      FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
3167                               &startFunc, &lastFunc, &startVar, &lastVar,
3168                               rowInfo, colInfo, rowOrder, colOrder, option);
3169      if (option->mlpVerbosity >= 2) {
3170        finalTime = util_cpu_time();
3171        fprintf(vis_stdout,
3172                "time for col singleton = %10g (#row=%d, #col=%d)\n",
3173                (double)(finalTime - initialTime) / 1000.0,
3174                saveLastFunc - lastFunc, saveLastVar - lastVar);
3175      }
3176    }
3177  }
3178
3179  if (option->mlpVerbosity >= 2) {
3180    initialTime = util_cpu_time();
3181    nLeftRows = lastFunc - startFunc + 1;
3182    nLeftCols = lastVar - startVar + 1;
3183  } else {
3184    /* To remove compiler warnings */
3185    initialTime = 0;
3186    nLeftRows = 0;
3187    nLeftCols = 0;
3188  }
3189
3190  if (option->mlpRowBased) {
3191    MoveBestRows(xy, sccList, nActiveRows, nActiveCols, rowOrder, colOrder,
3192                 rowInfo, colInfo,
3193                 startFunc, lastFunc, startVar, lastVar, option);
3194  } else {
3195    MoveBestCols(xy, sccList, nRows, nCols, nActiveRows, nActiveCols,
3196                 rowOrder, colOrder, rowInfo, colInfo,
3197                 startFunc, lastFunc, startVar, lastVar, option);
3198  }
3199
3200  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3201    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
3202                rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
3203  }
3204
3205  if (option->mlpVerbosity >= 2) {
3206    finalTime = util_cpu_time();
3207    if (option->mlpRowBased) {
3208      fprintf(vis_stdout, "time for best row = %10g (#row=%d, #col=%d)\n",
3209                (double)(finalTime - initialTime) / 1000.0,
3210                nLeftRows - lastFunc + startFunc - 1,
3211                nLeftCols - lastVar + startVar - 1);
3212    } else {
3213      fprintf(vis_stdout, "time for best col = %10g (#row=%d, #col=%d)\n",
3214                (double)(finalTime - initialTime) / 1000.0,
3215                nLeftRows - lastFunc + startFunc - 1,
3216                nLeftCols - lastVar + startVar - 1);
3217    }
3218  }
3219}
3220
3221
3222/**Function********************************************************************
3223
3224  Synopsis    [Finds and moves the best row iteratively.]
3225
3226  Description [Finds and moves the best row iteratively.]
3227
3228  SideEffects []
3229
3230******************************************************************************/
3231static void
3232MoveBestRows(char **xy, SccList_t *sccList, int nRows, int nCols,
3233                int *rowOrder, int *colOrder,
3234                RcInfo_t *rowInfo, RcInfo_t *colInfo,
3235                int startFunc, int lastFunc, int startVar, int lastVar,
3236                ImgTrmOption_t *option)
3237{
3238  int           x, y, s1, t1, s2, t2;
3239  int           min, bestX;
3240  int           row, col, lastCol, moveRow, bestRow;
3241  int           regionX, overlap, nOverlaps, nMore;
3242
3243  regionX = 0;
3244  bestX = -1;
3245  while (startFunc < lastFunc && startVar < lastVar) {
3246    min = nCols;
3247    overlap = 0;
3248    for (x = startFunc; x <= lastFunc; x++) {
3249      row = rowOrder[x];
3250      assert(rowInfo[row].lNum);
3251      if (overlap) {
3252        if (rowInfo[row].lNum < min) {
3253          s1 = colInfo[rowInfo[row].gMin].pos;
3254          if (s1 < regionX)
3255            s1 = regionX;
3256          nOverlaps = 0;
3257          for (y = s1; y < startVar; y++) {
3258            col = colOrder[y];
3259            if (xy[row][col]) {
3260              nOverlaps++;
3261              break;
3262            }
3263          }
3264
3265          if (nOverlaps) {
3266            bestX = x;
3267            min = rowInfo[row].lNum;
3268          }
3269        }
3270      } else {
3271        s1 = colInfo[rowInfo[row].gMin].pos;
3272        if (s1 < regionX)
3273          s1 = regionX;
3274        nOverlaps = 0;
3275        for (y = s1; y < startVar; y++) {
3276          col = colOrder[y];
3277          if (xy[row][col]) {
3278            nOverlaps++;
3279            break;
3280          }
3281        }
3282
3283        if (nOverlaps) {
3284          bestX = x;
3285          min = rowInfo[row].lNum;
3286          overlap = 1;
3287        } else {
3288          if (rowInfo[row].lNum < min) {
3289            bestX = x;
3290            min = rowInfo[row].lNum;
3291          }
3292        }
3293      }
3294    }
3295
3296    assert(bestX != -1);
3297    if (!overlap)
3298      regionX = startFunc;
3299
3300    row = rowOrder[bestX];
3301    while (1) {
3302      bestRow = row;
3303      s1 = colInfo[rowInfo[row].lMin].pos;
3304      t1 = colInfo[rowInfo[row].lMax].pos;
3305      min = rowInfo[row].lNum;
3306      for (x = startFunc; x <= lastFunc; x++) {
3307        moveRow = rowOrder[x];
3308        if (moveRow == row)
3309          continue;
3310        s2 = colInfo[rowInfo[moveRow].lMin].pos;
3311        t2 = colInfo[rowInfo[moveRow].lMax].pos;
3312        if (s2 < s1 || t2 > t1)
3313          continue;
3314        nMore = 0;
3315        nOverlaps = 0;
3316        for (y = s2; y <= t2; y++) {
3317          col = colOrder[y];
3318          if (xy[row][col]) {
3319            if (xy[moveRow][col])
3320              nOverlaps++;
3321          } else {
3322            if (xy[moveRow][col]) {
3323              nMore++;
3324              break;
3325            }
3326          }
3327        }
3328        if (nMore || nOverlaps == 0 || nOverlaps >= min)
3329          continue;
3330        min = nOverlaps;
3331        bestRow = moveRow;
3332      }
3333
3334      lastCol = -1;
3335      s1 = colInfo[rowInfo[bestRow].lMin].pos;
3336      t1 = colInfo[rowInfo[bestRow].lMax].pos;
3337      for (y = s1; y <= t1; y++) {
3338        col = colOrder[y];
3339        if (xy[bestRow][col]) {
3340          if (option->mlpVerbosity >= 3) {
3341            fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (best row)\n",
3342                    nMoves, y, col, startVar);
3343            fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3344                    startFunc, lastFunc, startVar, lastVar);
3345          }
3346          MoveColToLeft(xy, y, startFunc, lastFunc, startVar, lastVar,
3347                          rowInfo, colInfo, rowOrder, colOrder,
3348                          NIL(RcListInfo_t), option->mlpMethod);
3349          startVar++;
3350          lastCol = col;
3351
3352          if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3353            PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
3354                        startFunc, lastFunc, startVar, lastVar);
3355          }
3356          if (option->mlpDebug) {
3357            CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
3358                        rowOrder, colOrder,
3359                        startFunc, lastFunc, startVar, lastVar, 1);
3360          }
3361        }
3362      }
3363
3364      if (lastCol != -1) {
3365        s2 = rowInfo[colInfo[lastCol].lMin].pos;
3366        t2 = rowInfo[colInfo[lastCol].lMax].pos;
3367        for (x = s2; x <= t2; x++) {
3368          moveRow = rowOrder[x];
3369          if (xy[moveRow][lastCol] && rowInfo[moveRow].lNum == 0) {
3370            if (option->mlpVerbosity >= 3) {
3371              fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (best row)\n",
3372                        nMoves, x, moveRow, startFunc);
3373              fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3374                        startFunc, lastFunc, startVar, lastVar);
3375            }
3376            MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
3377                         rowInfo, colInfo, rowOrder, colOrder,
3378                         NIL(RcListInfo_t), option->mlpMethod);
3379            startFunc++;
3380            if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3381              PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
3382                          rowInfo, colInfo,
3383                          startFunc, lastFunc, startVar, lastVar);
3384            }
3385            if (option->mlpDebug) {
3386              CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
3387                          rowOrder, colOrder,
3388                          startFunc, lastFunc, startVar, lastVar, 1);
3389            }
3390          }
3391        }
3392      }
3393
3394      if (row == bestRow)
3395        break;
3396    }
3397  }
3398}
3399
3400
3401/**Function********************************************************************
3402
3403  Synopsis    [Finds and moves the best column iteratively.]
3404
3405  Description [Finds and moves the best column iteratively.]
3406
3407  SideEffects []
3408
3409******************************************************************************/
3410static void
3411MoveBestCols(char **xy, SccList_t *sccList, int nRows, int nCols,
3412                int nActiveRows, int nActiveCols,
3413                int *rowOrder, int *colOrder,
3414                RcInfo_t *rowInfo, RcInfo_t *colInfo,
3415                int startFunc, int lastFunc, int startVar, int lastVar,
3416                ImgTrmOption_t *option)
3417{
3418  int           x, y, i, s1, t1, s2, t2;
3419  char          *rowFlag, *colFlag;
3420  int           min, bestY, bestCol;
3421  int           row, col, tie, newTies, intersect = 0, maxIntersect, maxLength;
3422  int           minX, maxX;
3423  RcListInfo_t  *sortedRows, *sortedCols;
3424  RcList_t      *cur, *list;
3425
3426  if (option->mlpSortedRows) {
3427    sortedRows = SortedListAlloc();
3428    for (x = startFunc; x <= lastFunc; x++) {
3429      row = rowOrder[x];
3430      SortedListInsert(sortedRows, row, row, rowInfo, 3);
3431    }
3432
3433    if (option->mlpSortedCols)
3434      sortedCols = SortedListAlloc();
3435    else
3436      sortedCols = NIL(RcListInfo_t);
3437
3438    if (option->mlpDebug)
3439      CheckSortedList(sortedRows, rowInfo, 3);
3440  } else {
3441    sortedRows = NIL(RcListInfo_t);
3442    sortedCols = NIL(RcListInfo_t);
3443  }
3444
3445  rowFlag = ALLOC(char, nRows);
3446  if (sortedCols)
3447    memset(rowFlag, 0, sizeof(char) * nRows);
3448  colFlag = ALLOC(char, nCols);
3449  while (startFunc != lastFunc && startVar != lastVar) {
3450    min = nActiveCols;
3451    if (!sortedCols)
3452      memset(rowFlag, 0, sizeof(char) * nRows);
3453    tie = 0;
3454    minX = lastFunc;
3455    maxX = startFunc;
3456    if (sortedCols) {
3457      bestY = nActiveCols;
3458      bestCol = nActiveCols;
3459      if (sortedCols->num == 0) {
3460        if (sortedRows) {
3461          cur = sortedRows->head;
3462          while (cur) {
3463            row = cur->index;
3464            x = rowInfo[row].pos;
3465            if (rowInfo[row].lNum == 0) {
3466              cur = cur->next;
3467              continue;
3468            }
3469            if (rowInfo[row].lNum > min)
3470              break;
3471            rowFlag[row] = 1;
3472            s1 = colInfo[rowInfo[row].lMin].pos;
3473            t1 = colInfo[rowInfo[row].lMax].pos;
3474            for (y = s1; y <= t1; y++) {
3475              col = colOrder[y];
3476              if (!xy[row][col])
3477                continue;
3478              if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
3479                list->otherIndex++;
3480                SortedListMove(sortedCols, colInfo, col, 4);
3481              } else
3482                SortedListInsert(sortedCols, col, 1, colInfo, 4);
3483            }
3484            min = rowInfo[row].lNum;
3485            tie++;
3486            cur = cur->next;
3487          }
3488        }
3489      } else {
3490        if (sortedRows) {
3491          cur = sortedRows->head;
3492          while (cur) {
3493            row = cur->index;
3494            x = rowInfo[row].pos;
3495            if (rowInfo[row].lNum == 0) {
3496              cur = cur->next;
3497              continue;
3498            }
3499            if (rowInfo[row].lNum > min)
3500              break;
3501            min = rowInfo[row].lNum;
3502            tie++;
3503            cur = cur->next;
3504          }
3505        }
3506      }
3507
3508      if (option->mlpDebug) {
3509        if (sortedRows)
3510          CheckSortedList(sortedRows, rowInfo, 3);
3511        CheckSortedList(sortedCols, colInfo, 4);
3512      }
3513
3514      bestCol = sortedCols->head->index;
3515      bestY = colInfo[bestCol].pos;
3516      assert(bestY >= startVar && bestY <= lastVar);
3517      maxLength = colInfo[bestCol].lNum;
3518      intersect = sortedCols->head->otherIndex;
3519    } else {
3520      if (sortedRows) {
3521        if (option->mlpDebug)
3522          CheckSortedList(sortedRows, rowInfo, 3);
3523
3524        cur = sortedRows->head;
3525        while (cur) {
3526          row = cur->index;
3527          x = rowInfo[row].pos;
3528          if (rowInfo[row].lNum == 0) {
3529            cur = cur->next;
3530            continue;
3531          }
3532          if (rowInfo[row].lNum < min) {
3533            min = rowInfo[row].lNum;
3534            tie = 1;
3535            memset(rowFlag, 0, sizeof(char) * nRows);
3536            rowFlag[x] = 1;
3537            minX = x;
3538            maxX = x;
3539          } else if (rowInfo[row].lNum == min) {
3540            tie++;
3541            rowFlag[x] = 1;
3542            if (x < minX)
3543              minX = x;
3544            if (x > maxX)
3545              maxX = x;
3546          } else
3547            break;
3548          cur = cur->next;
3549        }
3550      } else {
3551        for (x = startFunc; x <= lastFunc; x++) {
3552          row = rowOrder[x];
3553          if (rowInfo[row].lNum == 0)
3554            continue;
3555          if (rowInfo[row].lNum < min) {
3556            min = rowInfo[row].lNum;
3557            tie = 1;
3558            memset(rowFlag, 0, sizeof(char) * nRows);
3559            rowFlag[x] = 1;
3560            minX = x;
3561            maxX = x;
3562          } else if (rowInfo[row].lNum == min) {
3563            tie++;
3564            rowFlag[x] = 1;
3565            maxX = x;
3566          }
3567        }
3568      }
3569
3570      if (tie == 0)
3571        break;
3572
3573      maxLength = 0;
3574      maxIntersect = 0;
3575      memset(colFlag, 0, sizeof(char) * nCols);
3576      bestY = nActiveCols;
3577      bestCol = nActiveCols;
3578      for (x = minX; x <= maxX; x++) {
3579        if (!rowFlag[x])
3580          continue;
3581        row = rowOrder[x];
3582        s1 = colInfo[rowInfo[row].lMin].pos;
3583        t1 = colInfo[rowInfo[row].lMax].pos;
3584        for (y = s1; y <= t1; y++) {
3585          col = colOrder[y];
3586          if (xy[row][col]) {
3587            if (colFlag[y])
3588              continue;
3589            colFlag[y] = 1;
3590            intersect = 0;
3591            s2 = rowInfo[colInfo[col].lMin].pos;
3592            t2 = rowInfo[colInfo[col].lMax].pos;
3593            if (s2 < minX)
3594              s2 = minX;
3595            if (t2 > maxX)
3596              t2 = maxX;
3597            for (i = s2; i <= t2; i++) {
3598              if (xy[rowOrder[i]][col]) {
3599                if (rowFlag[i])
3600                  intersect++;
3601              }
3602            }
3603            if (intersect > maxIntersect ||
3604                (intersect == maxIntersect && colInfo[col].lNum > maxLength) ||
3605                (intersect == maxIntersect && colInfo[col].lNum == maxLength &&
3606                  y < bestY)) {
3607              bestY = y;
3608              bestCol = colOrder[bestY];
3609              maxLength = colInfo[bestCol].lNum;
3610              maxIntersect = intersect;
3611            }
3612          }
3613        }
3614      }
3615    }
3616
3617    if (option->mlpVerbosity >= 3) {
3618      fprintf(vis_stdout,
3619"[%d] Moving Col %d(%d) to %d (best col, min=%d, intersect=%d, length=%d)\n",
3620             nMoves, bestY, bestCol, startVar, min, intersect, maxLength);
3621      fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3622             startFunc, lastFunc, startVar, lastVar);
3623    }
3624    MoveColToLeft(xy, bestY, startFunc, lastFunc, startVar, lastVar,
3625                  rowInfo, colInfo, rowOrder, colOrder,
3626                  NIL(RcListInfo_t), option->mlpMethod);
3627    startVar++;
3628    if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3629      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
3630                  rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
3631    }
3632    if (option->mlpDebug) {
3633      CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
3634                  rowOrder, colOrder,
3635                  startFunc, lastFunc, startVar, lastVar, 1);
3636    }
3637
3638    if (sortedCols)
3639      SortedListDelete(sortedCols, bestCol);
3640
3641    if (sortedRows) {
3642      if (min == 1) {
3643        cur = sortedRows->head;
3644        while (cur) {
3645          row = cur->index;
3646          if (rowInfo[row].lNum > min)
3647            break;
3648          else if (rowInfo[row].lNum == min) {
3649            cur = cur->next;
3650            continue;
3651          }
3652          x = rowInfo[row].pos;
3653          if (option->mlpVerbosity >= 3) {
3654            fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
3655                   nMoves, x, row, startFunc);
3656            fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3657                   startFunc, lastFunc, startVar, lastVar);
3658          }
3659          MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
3660                       rowInfo, colInfo, rowOrder, colOrder,
3661                       NIL(RcListInfo_t), option->mlpMethod);
3662          startFunc++;
3663          if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3664            PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
3665                        rowInfo, colInfo,
3666                        startFunc, lastFunc, startVar, lastVar);
3667          }
3668          if (option->mlpDebug) {
3669            CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
3670                        rowInfo, colInfo, rowOrder, colOrder,
3671                        startFunc, lastFunc, startVar, lastVar, 1);
3672          }
3673          cur = cur->next;
3674          SortedListDelete(sortedRows, row);
3675        }
3676      }
3677
3678      /* Update sortedRows */
3679      /*
3680      cur = sortedRows->head;
3681      while (cur) {
3682        row = cur->index;
3683        if (xy[row][bestCol]) {
3684          assert(rowInfo[row].lNum > 0);
3685          SortedListMove(sortedRows, rowInfo, row, 3);
3686        }
3687        cur = cur->next;
3688      }
3689      if (option->mlpDebug)
3690        CheckSortedList(sortedRows, rowInfo, 3);
3691      */
3692      s1 = rowInfo[colInfo[bestCol].lMin].pos;
3693      t1 = rowInfo[colInfo[bestCol].lMax].pos;
3694      cur = sortedRows->head;
3695      while (cur) {
3696        row = cur->index;
3697        x = rowInfo[row].pos;
3698        if (x < s1) {
3699          cur = cur->next;
3700          continue;
3701        }
3702        if (xy[row][bestCol] && rowInfo[row].lNum > 0) {
3703          SortedListMove(sortedRows, rowInfo, row, 3);
3704          if (sortedCols && min == 1) {
3705            if (rowInfo[row].lNum == 1 && rowFlag[row] == 0) {
3706              rowFlag[row] = 1;
3707              s2 = colInfo[rowInfo[row].lMin].pos;
3708              t2 = colInfo[rowInfo[row].lMax].pos;
3709              for (y = s2; y <= t2; y++) {
3710                col = colOrder[y];
3711                if (!xy[row][col])
3712                  continue;
3713                if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
3714                  list->otherIndex++;
3715                  SortedListMove(sortedCols, colInfo, col, 4);
3716                } else
3717                  SortedListInsert(sortedCols, col, 1, colInfo, 4);
3718              }
3719            }
3720          }
3721        }
3722        cur = cur->next;
3723      }
3724
3725      newTies = 0;
3726      if (sortedCols && min > 1) {
3727        min = nActiveCols;
3728        cur = sortedRows->head;
3729        while (cur) {
3730          row = cur->index;
3731          x = rowInfo[row].pos;
3732          if (rowInfo[row].lNum == 0) {
3733            cur = cur->next;
3734            continue;
3735          }
3736          if (rowInfo[row].lNum > min)
3737            break;
3738          min = rowInfo[row].lNum;
3739          newTies++;
3740          cur = cur->next;
3741        }
3742
3743        if (newTies != tie) {
3744          SortedListFree(sortedCols);
3745          sortedCols = SortedListAlloc();
3746
3747          cur = sortedRows->head;
3748          while (cur) {
3749            row = cur->index;
3750            x = rowInfo[row].pos;
3751            if (rowInfo[row].lNum == 0) {
3752              cur = cur->next;
3753              continue;
3754            }
3755            if (rowInfo[row].lNum > min)
3756              break;
3757            rowFlag[row] = 1;
3758            s1 = colInfo[rowInfo[row].lMin].pos;
3759            t1 = colInfo[rowInfo[row].lMax].pos;
3760            for (y = s1; y <= t1; y++) {
3761              col = colOrder[y];
3762              if (!xy[row][col])
3763                continue;
3764              if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
3765                list->otherIndex++;
3766                SortedListMove(sortedCols, colInfo, col, 4);
3767              } else
3768                SortedListInsert(sortedCols, col, 1, colInfo, 4);
3769            }
3770            cur = cur->next;
3771          }
3772        }
3773      }
3774    } else {
3775      if (min == 1) {
3776        s1 = rowInfo[colInfo[bestCol].lMin].pos;
3777        t1 = rowInfo[colInfo[bestCol].lMax].pos;
3778        for (x = s1; x <= t1; x++) {
3779          row = rowOrder[x];
3780          if (xy[row][bestCol] && rowInfo[row].lNum == 0) {
3781            if (option->mlpVerbosity >= 3) {
3782              fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
3783                     nMoves, x, row, startFunc);
3784              fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3785                     startFunc, lastFunc, startVar, lastVar);
3786            }
3787            MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
3788                         rowInfo, colInfo, rowOrder, colOrder,
3789                         NIL(RcListInfo_t), option->mlpMethod);
3790            startFunc++;
3791            if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3792              PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
3793                          rowInfo, colInfo,
3794                          startFunc, lastFunc, startVar, lastVar);
3795            }
3796            if (option->mlpDebug) {
3797              CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
3798                          rowInfo, colInfo, rowOrder, colOrder,
3799                          startFunc, lastFunc, startVar, lastVar, 1);
3800            }
3801          }
3802        }
3803      }
3804    }
3805  }
3806
3807  if (sortedRows) {
3808    cur = sortedRows->head;
3809    while (cur) {
3810      row = cur->index;
3811      x = rowInfo[row].pos;
3812      if (option->mlpVerbosity >= 3) {
3813        fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (bandwidth)\n",
3814               nMoves, x, row, startFunc);
3815        fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
3816               startFunc, lastFunc, startVar, lastVar);
3817      }
3818      MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
3819                   rowInfo, colInfo, rowOrder, colOrder,
3820                   NIL(RcListInfo_t), option->mlpMethod);
3821      startFunc++;
3822      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3823        PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
3824                    rowInfo, colInfo,
3825                    startFunc, lastFunc, startVar, lastVar);
3826      }
3827      if (option->mlpDebug) {
3828        CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
3829                    rowOrder, colOrder,
3830                    startFunc, lastFunc, startVar, lastVar, 1);
3831      }
3832      cur = cur->next;
3833      SortedListDelete(sortedRows, row);
3834    }
3835    SortedListFree(sortedRows);
3836  }
3837
3838  if (sortedCols) {
3839    cur = sortedCols->head;
3840    while (cur) {
3841      col = cur->index;
3842      cur = cur->next;
3843      SortedListDelete(sortedCols, col);
3844    }
3845    SortedListFree(sortedCols);
3846  }
3847
3848  FREE(rowFlag);
3849  FREE(colFlag);
3850}
3851
3852
3853/**Function********************************************************************
3854
3855  Synopsis    [Performs a postprocessing after MLP.]
3856
3857  Description [Performs a postprocessing after MLP. Tries to exchange adjacent
3858  two rows if the exchange lowers variable lifetime.]
3859
3860  SideEffects []
3861
3862******************************************************************************/
3863static void
3864MlpPostProcess(char **xy, SccList_t *sccList, int nVars, int nRows, int nCols,
3865                RcInfo_t *rowInfo, RcInfo_t *colInfo,
3866                int *rowOrder, int *colOrder,
3867                Img_DirectionType direction, ImgTrmOption_t *option)
3868{
3869  int           x, y, i, j, r, c, row, col, otherRow, otherCol, tmpRow, tmpCol;
3870  int           nqv1, nqv2, niv1, niv2, benefit1, benefit2;
3871  int           s1, t1, s2, t2, s3, t3, s4, t4;
3872  long          initialTime, finalTime;
3873  int           nSwaps;
3874  float         lambda1, lambda2, lambda3;
3875  int           startFunc, lastFunc;
3876
3877  if (sccList) {
3878    startFunc = sccList->startFunc;
3879    lastFunc = sccList->lastFunc;
3880  } else {
3881    startFunc = 0;
3882    lastFunc = nRows - 1;
3883  }
3884
3885  if (option->mlpVerbosity)
3886    initialTime = util_cpu_time();
3887  else
3888    initialTime = 0;
3889
3890  nSwaps = 0;
3891  for (x = lastFunc - 1; x >= startFunc; x--) {
3892    row = rowOrder[x];
3893    if (rowInfo[row].data.row.nsVarBddArray)
3894      niv1 = array_n(rowInfo[row].data.row.nsVarBddArray);
3895    else
3896      niv1 = 0;
3897
3898    col = rowInfo[row].gMin;
3899    if (rowInfo[row].gNum == 1 &&
3900        colInfo[col].gNum > 1 && colInfo[col].gMin == x) {
3901      t1 = rowInfo[colInfo[col].gMax].pos;
3902      for (i = x + 1; i <= t1; i++) {
3903        otherRow = rowOrder[i];
3904        if (xy[otherRow][col]) {
3905          if (x < i - 1) {
3906            for (j = x; j < i - 1; j++) {
3907              rowOrder[j] = rowOrder[j + 1];
3908              rowInfo[rowOrder[j]].pos = j;
3909            }
3910            rowOrder[i - 1] = row;
3911            rowInfo[row].pos = i - 1;
3912
3913            if (rowInfo[otherRow].gNum == 1)
3914              break;
3915
3916            s2 = colInfo[rowInfo[otherRow].gMin].pos;
3917            t2 = colInfo[rowInfo[otherRow].gMax].pos;
3918            for (j = t2; j >= s2; j--) {
3919              otherCol = colOrder[j];
3920              if (colInfo[otherCol].gMin == otherRow)
3921                t2 = j - 1;
3922              else
3923                break;
3924            }
3925
3926            s3 = rowInfo[colInfo[col].gMin].pos;
3927            t3 = rowInfo[colInfo[col].gMax].pos;
3928            for (r = s3; r <= t3; r++) {
3929              tmpRow = rowOrder[r];
3930              if (col == rowInfo[tmpRow].gMin) {
3931                s4 = colInfo[rowInfo[tmpRow].gMin].pos;
3932                t4 = colInfo[rowInfo[tmpRow].gMax].pos;
3933                if (t4 > t2)
3934                  t4 = t2;
3935                for (c = s4 + 1; c <= t4; c++) {
3936                  tmpCol = colOrder[c];
3937                  if (xy[tmpRow][tmpCol]) {
3938                    rowInfo[tmpRow].gMin = tmpCol;
3939                    rowInfo[tmpRow].lMin = tmpCol;
3940                    break;
3941                  }
3942                }
3943              }
3944
3945              if (xy[tmpRow][col] && t2 >= colInfo[rowInfo[tmpRow].gMax].pos) {
3946                rowInfo[tmpRow].gMax = col;
3947                rowInfo[tmpRow].lMax = col;
3948              }
3949            }
3950
3951            y = colInfo[col].pos;
3952            if (y < t2) {
3953              for (j = y; j < t2; j++) {
3954                colOrder[j] = colOrder[j + 1];
3955                colInfo[colOrder[j]].pos = j;
3956              }
3957              colOrder[t2] = col;
3958              colInfo[col].pos = t2;
3959            }
3960
3961            if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
3962              PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
3963                          rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
3964            }
3965            if (option->mlpDebug) {
3966              CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
3967                          rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
3968            }
3969
3970            nSwaps++;
3971          }
3972          break;
3973        }
3974      }
3975      continue;
3976    }
3977
3978    for (i = x + 1; i <= lastFunc; i++) {
3979      otherRow = rowOrder[i];
3980      if (rowInfo[otherRow].data.row.nsVarBddArray)
3981        niv2 = array_n(rowInfo[otherRow].data.row.nsVarBddArray);
3982      else
3983        niv2 = 0;
3984
3985      nqv1 = 0;
3986      s1 = colInfo[rowInfo[row].gMin].pos;
3987      t1 = colInfo[rowInfo[row].gMax].pos;
3988      for (y = t1; y >= s1; y--) {
3989        col = colOrder[y];
3990        if (colInfo[col].gMin == row) {
3991          if (!xy[otherRow][col])
3992            nqv1++;
3993        } else
3994          break;
3995      }
3996      benefit1 = nqv1 - niv1;
3997
3998      nqv2 = 0;
3999      s2 = colInfo[rowInfo[otherRow].gMin].pos;
4000      t2 = colInfo[rowInfo[otherRow].gMax].pos;
4001      for (y = t2; y >= s2; y--) {
4002        col = colOrder[y];
4003        if (colInfo[col].gMin == otherRow)
4004          nqv2++;
4005        else
4006          break;
4007      }
4008      benefit2 = nqv2 - niv2;
4009
4010      if (benefit1 > benefit2 ||
4011          (benefit1 == benefit2 &&
4012           (rowInfo[row].gNum > rowInfo[otherRow].gNum ||
4013            (rowInfo[row].gNum == rowInfo[otherRow].gNum &&
4014             bdd_size(rowInfo[row].data.row.func) <
4015             bdd_size(rowInfo[otherRow].data.row.func))))) {
4016        nqv1 = 0;
4017        for (y = t1; y >= s1; y--) {
4018          if (t1 > t2)
4019            break;
4020          col = colOrder[y];
4021          if (colInfo[col].gMin == row) {
4022            if (!xy[otherRow][col]) {
4023              s3 = rowInfo[colInfo[col].gMin].pos;
4024              t3 = rowInfo[colInfo[col].gMax].pos;
4025              for (r = s3; r <= t3; r++) {
4026                tmpRow = rowOrder[r];
4027                if (col == rowInfo[tmpRow].gMin) {
4028                  s4 = colInfo[rowInfo[tmpRow].gMin].pos;
4029                  t4 = colInfo[rowInfo[tmpRow].gMax].pos;
4030                  if (t4 > t2 - nqv1)
4031                    t4 = t2 - nqv1;
4032                  for (c = s4 + 1; c <= t4; c++) {
4033                    tmpCol = colOrder[c];
4034                    if (xy[tmpRow][tmpCol] && colInfo[tmpCol].gMin != row) {
4035                      rowInfo[tmpRow].gMin = tmpCol;
4036                      rowInfo[tmpRow].lMin = tmpCol;
4037                      break;
4038                    }
4039                  }
4040                }
4041
4042                if (nqv1 == 0 && xy[tmpRow][col] &&
4043                    t2 - nqv1 >= colInfo[rowInfo[tmpRow].gMax].pos) {
4044                  rowInfo[tmpRow].gMax = col;
4045                  rowInfo[tmpRow].lMax = col;
4046                }
4047              }
4048
4049              for (j = y; j < t2 - nqv1; j++) {
4050                colOrder[j] = colOrder[j + 1];
4051                colInfo[colOrder[j]].pos = j;
4052              }
4053              colOrder[t2 - nqv1] = col;
4054              colInfo[col].pos = t2 - nqv1;
4055              nqv1++;
4056            } else {
4057              colInfo[col].gMin = otherRow;
4058              colInfo[col].lMin = otherRow;
4059              if (colInfo[col].gMax == otherRow) {
4060                colInfo[col].gMax = row;
4061                colInfo[col].lMax = row;
4062              }
4063            }
4064          } else {
4065            if (colInfo[col].gMax == otherRow && xy[row][col]) {
4066              colInfo[col].gMax = row;
4067              colInfo[col].lMax = row;
4068            }
4069          }
4070        }
4071
4072        rowOrder[i - 1] = otherRow;
4073        rowInfo[otherRow].pos = i - 1;
4074        rowOrder[i] = row;
4075        rowInfo[row].pos = i;
4076        nSwaps++;
4077
4078        if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
4079          PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
4080                        rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
4081        }
4082        if (option->mlpDebug) {
4083          CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
4084                        rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
4085        }
4086      } else
4087        break;
4088    }
4089  }
4090
4091  if (option->mlpVerbosity) {
4092    if (option->mlpVerbosity >= 2) {
4093      lambda1 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
4094                                 rowOrder, colOrder, direction, 0, 0, option);
4095      lambda2 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
4096                                 rowOrder, colOrder, direction, 1, 0, option);
4097      lambda3 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
4098                                 rowOrder, colOrder, direction, 2, 0, option);
4099      fprintf(vis_stdout, "Optimized Lambda = %f (%f, %f)\n",
4100              lambda1, lambda2, lambda3);
4101    }
4102    finalTime = util_cpu_time();
4103    fprintf(vis_stdout, "time for postprocessing = %10g (#swap=%d)\n",
4104           (double)(finalTime - initialTime) / 1000.0, nSwaps);
4105  }
4106}
4107
4108
4109/**Function********************************************************************
4110
4111  Synopsis    [Compute variable lifetime lambda.]
4112
4113  Description [Compute variable lifetime lambda.]
4114
4115  SideEffects []
4116
4117******************************************************************************/
4118static float
4119ComputeLambdaMlp(char **xy, int nVars, int nRows, int nCols,
4120                RcInfo_t *rowInfo, RcInfo_t *colInfo,
4121                int *rowOrder, int *colOrder,
4122                Img_DirectionType direction,
4123                int mode, int asIs, ImgTrmOption_t *option)
4124{
4125  int           lifetime, area;
4126  int           highest, lowest;
4127  int           x, y, row, col;
4128  int           nIntroducedVars, nYVars;
4129  float         lambda;
4130
4131  lifetime = 0;
4132
4133  if (direction == Img_Forward_c) {
4134    for (y = 0; y < nCols; y++) {
4135      col = colOrder[y];
4136      lowest = rowInfo[colInfo[col].gMin].pos;
4137      if (mode == 1) { /* active lifetime (alpha) */
4138        highest = rowInfo[colInfo[col].gMax].pos;
4139        lifetime += highest - lowest + 1;
4140      } else { /* total lifetime (lambda) */
4141        lifetime += nRows - lowest;
4142      }
4143    }
4144  } else {
4145    for (y = 0; y < nCols; y++) {
4146      col = colOrder[y];
4147      lowest = rowInfo[colInfo[col].gMin].pos;
4148      if (mode == 1) { /* active lifetime (alpha) */
4149        highest = rowInfo[colInfo[col].gMax].pos;
4150        lifetime += highest - lowest + 1;
4151      } else { /* total lifetime (lambda) */
4152        if (colInfo[col].data.col.type == 2) /* primary input variables */
4153          lifetime += lowest + 1;
4154        else { /* present state variables */
4155          if (mode == 2)
4156            lifetime += nRows - lowest;
4157        }
4158      }
4159    }
4160  }
4161
4162  /* total lifetime (lambda) with introducedVars */
4163  nIntroducedVars = 0;;
4164  if (mode == 2 || (mode == 0 && direction == Img_Backward_c)) {
4165    if (asIs) { /* contains next state variables */
4166      for (x = 0; x < nRows; x++) {
4167        row = rowOrder[x];
4168        nYVars = array_n(rowInfo[row].data.row.nsVarBddArray);
4169        nIntroducedVars += nYVars;
4170        lifetime += (x + 1) * nYVars;
4171      }
4172    } else { /* does not contain next state variables */
4173      nIntroducedVars = nRows;
4174      lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
4175    }
4176  }
4177
4178  if (option->mlpLambdaMode == 0)
4179    area = nRows * (nCols + nIntroducedVars);
4180  else
4181    area = nRows * (nVars + nIntroducedVars);
4182  lambda = (float)lifetime / (float)area;
4183  return(lambda);
4184}
4185
4186
4187/**Function********************************************************************
4188
4189  Synopsis    [Finds and moves singleton rows.]
4190
4191  Description [Finds and moves singleton rows.]
4192
4193  SideEffects []
4194
4195******************************************************************************/
4196static void
4197FindAndMoveSingletonRows(char **xy, SccList_t *sccList, int nRows, int nCols,
4198        int *startFunc, int *lastFunc, int *startVar, int *lastVar,
4199        RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4200        ImgTrmOption_t *option)
4201{
4202  int           x, row, col, add, found;
4203  RcListInfo_t  *candList;
4204
4205  if (option->mlpMethod == 0) {
4206    while (*startFunc != *lastFunc && *startVar != *lastVar) {
4207      found = 0;
4208      for (x = *startFunc; x <= *lastFunc; x++) {
4209        row = rowOrder[x];
4210        if (rowInfo[row].lNum == 1) {
4211          found = 1;
4212          add = MoveSingletonRow(xy, sccList, nRows, nCols, x,
4213                                startFunc, lastFunc, startVar, lastVar,
4214                                rowInfo, colInfo, rowOrder, colOrder,
4215                                NIL(RcListInfo_t), option);
4216          if (*startFunc == *lastFunc || *startVar == *lastVar) {
4217            found = 0;
4218            break;
4219          }
4220          x += add;
4221        }
4222      }
4223      if (!found)
4224        break;
4225    }
4226  } else {
4227    if (*startFunc != *lastFunc && *startVar != *lastVar) {
4228      candList = SortedListAlloc();
4229      for (x = *startFunc; x <= *lastFunc; x++) {
4230        row = rowOrder[x];
4231        if (rowInfo[row].lNum == 1) {
4232          col = rowInfo[row].lMin;
4233          SortedListInsert(candList, row, col, colInfo, option->mlpMethod);
4234        }
4235      }
4236      if (option->mlpDebug)
4237        CheckSortedList(candList, colInfo, option->mlpMethod);
4238      while (candList->cur) {
4239        candList->curIndex = candList->cur->index;
4240        x = rowInfo[candList->curIndex].pos;
4241        MoveSingletonRow(xy, sccList, nRows, nCols, x,
4242                        startFunc, lastFunc, startVar, lastVar,
4243                        rowInfo, colInfo, rowOrder, colOrder,
4244                        candList, option);
4245        if (option->mlpDebug)
4246          CheckSortedList(candList, colInfo, option->mlpMethod);
4247        if (*startFunc == *lastFunc || *startVar == *lastVar) {
4248          break;
4249        }
4250      }
4251      if (option->mlpVerbosity) {
4252        fprintf(vis_stdout, "max number of elements in list = %d\n",
4253                candList->maxNum);
4254      }
4255      SortedListFree(candList);
4256    }
4257  }
4258}
4259
4260
4261/**Function********************************************************************
4262
4263  Synopsis    [Moves a singleton row.]
4264
4265  Description [Moves a singleton row.]
4266
4267  SideEffects []
4268
4269******************************************************************************/
4270static int
4271MoveSingletonRow(char **xy, SccList_t *sccList, int nRows, int nCols, int x,
4272        int *startFunc, int *lastFunc, int *startVar, int *lastVar,
4273        RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4274        RcListInfo_t *candList, ImgTrmOption_t *option)
4275{
4276  int   y, i, add;
4277  int   row, col, otherRow;
4278  int   startRow, lastRow, startCol, lastCol;
4279
4280  startRow = *startFunc;
4281  startCol = *startVar;
4282  lastRow = *lastFunc;
4283  lastCol = *lastVar;
4284
4285  row = rowOrder[x];
4286  col = rowInfo[row].lMin;
4287  y = colInfo[col].pos;
4288
4289  if (option->mlpVerbosity >= 3) {
4290    fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (row singleton)\n",
4291          nMoves, y, col, startCol);
4292    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
4293           startRow, lastRow, startCol, lastCol);
4294  }
4295  MoveColToLeft(xy, y, startRow, lastRow, startCol, lastCol,
4296                rowInfo, colInfo, rowOrder, colOrder, candList,
4297                option->mlpMethod);
4298  startCol++;
4299  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
4300    PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
4301                startRow, lastRow, startCol, lastCol);
4302  }
4303  if (option->mlpDebug) {
4304    CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
4305                startRow, lastRow, startCol, lastCol, 1);
4306  }
4307
4308  add = 0;
4309  for (i = rowInfo[colInfo[col].lMin].pos;
4310       colInfo[col].lNum && i <= rowInfo[colInfo[col].lMax].pos; i++) {
4311    otherRow = rowOrder[i];
4312    if (!xy[otherRow][col])
4313      continue;
4314    if (rowInfo[otherRow].lNum == 0) {
4315      if (option->mlpVerbosity >= 3) {
4316        fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (row singleton)\n",
4317                nMoves, i, otherRow, startRow);
4318        fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
4319               startRow, lastRow, startCol, lastCol);
4320      }
4321      MoveRowToTop(xy, i, startRow, lastRow, startCol, lastCol,
4322                   rowInfo, colInfo, rowOrder, colOrder,
4323                   NIL(RcListInfo_t), option->mlpMethod);
4324      startRow++;
4325      if (i > x)
4326        add++;
4327      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
4328        PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
4329                    startRow, lastRow, startCol, lastCol);
4330      }
4331      if (option->mlpDebug) {
4332        CheckMatrix(xy, sccList, nRows, nCols,
4333                    rowInfo, colInfo, rowOrder, colOrder,
4334                    startRow, lastRow, startCol, lastCol, 1);
4335      }
4336    }
4337  }
4338
4339  *startFunc = startRow;
4340  *startVar = startCol;
4341  return(add);
4342}
4343
4344
4345/**Function********************************************************************
4346
4347  Synopsis    [Finds and moves singleton columns.]
4348
4349  Description [Finds and moves singleton columns.]
4350
4351  SideEffects []
4352
4353******************************************************************************/
4354static void
4355FindAndMoveSingletonCols(char **xy, SccList_t *sccList, int nRows, int nCols,
4356        int *startFunc, int *lastFunc, int *startVar, int *lastVar,
4357        RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4358        ImgTrmOption_t *option)
4359{
4360  int           y, row, col, add, found;
4361  RcListInfo_t  *candList;
4362
4363  if (option->mlpMethod == 0) {
4364    while (*startFunc != *lastFunc && *startVar != *lastVar) {
4365      found = 0;
4366      for (y = *startVar; y <= *lastVar; y++) {
4367        col = colOrder[y];
4368        if (colInfo[col].lNum == 1) {
4369          found = 1;
4370          add = MoveSingletonCol(xy, sccList, nRows, nCols, y,
4371                                startFunc, lastFunc, startVar, lastVar,
4372                                rowInfo, colInfo, rowOrder, colOrder,
4373                                NIL(RcListInfo_t), option);
4374          if (*startFunc == *lastFunc || *startVar == *lastVar) {
4375            found = 0;
4376            break;
4377          }
4378          y -= add;
4379        }
4380      }
4381      if (!found)
4382        break;
4383    }
4384  } else {
4385    if (*startFunc != *lastFunc && *startVar != *lastVar) {
4386      candList = SortedListAlloc();
4387      for (y = *startVar; y <= *lastVar; y++) {
4388        col = colOrder[y];
4389        if (colInfo[col].lNum == 1) {
4390          row = colInfo[col].lMin;
4391          SortedListInsert(candList, col, row, rowInfo, option->mlpMethod);
4392        }
4393      }
4394      if (option->mlpDebug)
4395        CheckSortedList(candList, rowInfo, option->mlpMethod);
4396      while (candList->cur) {
4397        candList->curIndex = candList->cur->index;
4398        y = colInfo[candList->curIndex].pos;
4399        MoveSingletonCol(xy, sccList, nRows, nCols, y,
4400                        startFunc, lastFunc, startVar, lastVar,
4401                        rowInfo, colInfo, rowOrder, colOrder, candList, option);
4402        if (option->mlpDebug)
4403          CheckSortedList(candList, rowInfo, option->mlpMethod);
4404        if (*startFunc == *lastFunc || *startVar == *lastVar) {
4405          break;
4406        }
4407      }
4408      if (option->mlpVerbosity >= 2) {
4409        fprintf(vis_stdout, "max number of elements in list = %d\n",
4410                candList->maxNum);
4411      }
4412      SortedListFree(candList);
4413    }
4414  }
4415}
4416
4417
4418/**Function********************************************************************
4419
4420  Synopsis    [Moves a singleton column.]
4421
4422  Description [Moves a singleton column.]
4423
4424  SideEffects []
4425
4426******************************************************************************/
4427static int
4428MoveSingletonCol(char **xy, SccList_t *sccList, int nRows, int nCols, int y,
4429        int *startFunc, int *lastFunc, int *startVar, int *lastVar,
4430        RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4431        RcListInfo_t *candList, ImgTrmOption_t *option)
4432{
4433  int   x, j, add;
4434  int   row, col, otherCol;
4435  int   startRow, lastRow, startCol, lastCol;
4436
4437  startRow = *startFunc;
4438  startCol = *startVar;
4439  lastRow = *lastFunc;
4440  lastCol = *lastVar;
4441
4442  col = colOrder[y];
4443  row = colInfo[col].lMin;
4444  x = rowInfo[row].pos;
4445
4446  if (option->mlpVerbosity >= 3) {
4447    fprintf(vis_stdout, "[%d] Moving Row %d(%d) to %d (col singleton)\n",
4448          nMoves, x, row, lastRow);
4449    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
4450           startRow, lastRow, startCol, lastCol);
4451  }
4452  MoveRowToBottom(xy, x, startRow, lastRow, startCol, lastCol,
4453                  rowInfo, colInfo, rowOrder, colOrder, candList,
4454                  option->mlpMethod);
4455  lastRow--;
4456  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
4457    PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
4458                startRow, lastRow, startCol, lastCol);
4459  }
4460  if (option->mlpDebug) {
4461    CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
4462                startRow, lastRow, startCol, lastCol, 1);
4463  }
4464
4465  add = 0;
4466  for (j = colInfo[rowInfo[row].lMin].pos;
4467       rowInfo[row].lNum && j <= colInfo[rowInfo[row].lMax].pos; j++) {
4468    otherCol = colOrder[j];
4469    if (!xy[row][otherCol])
4470      continue;
4471    if (colInfo[otherCol].lNum == 0) {
4472      if (option->mlpVerbosity >= 3) {
4473        fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (col singleton)\n",
4474                nMoves, j, otherCol, lastCol);
4475        fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
4476                startRow, lastRow, startCol, lastCol);
4477      }
4478      MoveColToRight(xy, j, startRow, lastRow, startCol, lastCol,
4479                     rowInfo, colInfo, rowOrder, colOrder,
4480                     NIL(RcListInfo_t), option->mlpMethod);
4481      lastCol--;
4482      j--;
4483      if (otherCol <= col)
4484        add++;
4485      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
4486        PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
4487                    startRow, lastRow, startCol, lastCol);
4488      }
4489      if (option->mlpDebug) {
4490        CheckMatrix(xy, sccList, nRows, nCols,
4491                    rowInfo, colInfo, rowOrder, colOrder,
4492                    startRow, lastRow, startCol, lastCol, 1);
4493      }
4494    }
4495  }
4496
4497  *lastFunc = lastRow;
4498  *lastVar = lastCol;
4499  return(add);
4500}
4501
4502
4503/**Function********************************************************************
4504
4505  Synopsis    [Moves a row to the top of the active region.]
4506
4507  Description [Moves a row to the top of the active region.]
4508
4509  SideEffects []
4510
4511******************************************************************************/
4512static void
4513MoveRowToTop(char **xy, int x, int startFunc, int lastFunc,
4514             int startVar, int lastVar, RcInfo_t *rowInfo,
4515             RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4516             RcListInfo_t *candList, int method)
4517{
4518  int   i, j, s, t;
4519  int   row, col, tmpRow;
4520
4521  assert(x >= startFunc && x <= lastFunc);
4522
4523  row = rowOrder[x];
4524  if (x != startFunc) {
4525    /* Change row order */
4526    for (i = x; i > startFunc; i--) {
4527      rowOrder[i] = rowOrder[i - 1];
4528      rowInfo[rowOrder[i]].pos = i;
4529    }
4530    rowOrder[startFunc] = row;
4531    rowInfo[row].pos = startFunc;
4532  }
4533
4534  s = colInfo[rowInfo[row].gMin].pos;
4535  t = colInfo[rowInfo[row].gMax].pos;
4536  for (j = s; j <= t; j++) {
4537    col = colOrder[j];
4538    if (!xy[row][col])
4539      continue;
4540    colInfo[col].prevG = startFunc;
4541    if (colInfo[col].lNum == 1) {
4542      colInfo[col].lMin = row;
4543      colInfo[col].lMax = row;
4544    } else {
4545      if (row == colInfo[col].lMin) {
4546        for (i = x + 1; i <= rowInfo[colInfo[col].lMax].pos; i++) {
4547          tmpRow = rowOrder[i];
4548          if (xy[tmpRow][col]) {
4549            colInfo[col].lMin = tmpRow;
4550            break;
4551          }
4552        }
4553      } else if (row == colInfo[col].lMax) {
4554        for (i = x; i >= rowInfo[colInfo[col].lMin].pos; i--) {
4555          tmpRow = rowOrder[i];
4556          if (xy[tmpRow][col]) {
4557            colInfo[col].lMax = tmpRow;
4558            break;
4559          }
4560        }
4561      }
4562    }
4563
4564    if (colInfo[col].gNum == 1) {
4565      colInfo[col].gMin = row;
4566      colInfo[col].gMax = row;
4567    } else {
4568      if (row == colInfo[col].gMin)
4569        colInfo[col].gMin = row;
4570      else if (row == colInfo[col].gMax) {
4571        colInfo[col].gMax = colInfo[col].lMax;
4572        if (startFunc <= rowInfo[colInfo[col].gMin].pos)
4573          colInfo[col].gMin = row;
4574      } else if (startFunc <= rowInfo[colInfo[col].gMin].pos)
4575        colInfo[col].gMin = row;
4576    }
4577
4578    if (rowInfo[row].lNum) {
4579      if (j == rowInfo[row].prevG)
4580        j = colInfo[rowInfo[row].lMin].pos - 1;
4581      else if (j == colInfo[rowInfo[row].lMax].pos)
4582        j = rowInfo[row].nextG - 1;
4583    }
4584  }
4585
4586  s = colInfo[rowInfo[row].lMin].pos;
4587  t = colInfo[rowInfo[row].lMax].pos;
4588  for (j = s; j <= t; j++) {
4589    col = colOrder[j];
4590    if (xy[row][col]) {
4591      colInfo[col].lNum--;
4592      if (candList) {
4593        if (colInfo[col].lNum == 0)
4594          SortedListDelete(candList, col);
4595        else if (colInfo[col].lNum == 1)
4596          SortedListInsert(candList, col, row, rowInfo, method);
4597      }
4598    }
4599  }
4600
4601  nMoves++;
4602}
4603
4604
4605/**Function********************************************************************
4606
4607  Synopsis    [Moves a column to the left of the active region.]
4608
4609  Description [Moves a column to the left of the active region.]
4610
4611  SideEffects []
4612
4613******************************************************************************/
4614static void
4615MoveColToLeft(char **xy, int y, int startFunc, int lastFunc,
4616              int startVar, int lastVar, RcInfo_t *rowInfo,
4617              RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4618              RcListInfo_t *candList, int method)
4619{
4620  int   i, j, s, t;
4621  int   row, col, tmpCol;
4622
4623  assert(y >= startVar && y <= lastVar);
4624
4625  col = colOrder[y];
4626  if (y != startVar) {
4627    /* Change col order */
4628    for (j = y; j > startVar; j--) {
4629      colOrder[j] = colOrder[j - 1];
4630      colInfo[colOrder[j]].pos = j;
4631    }
4632    colOrder[startVar] = col;
4633    colInfo[col].pos = startVar;
4634  }
4635
4636  s = rowInfo[colInfo[col].gMin].pos;
4637  t = rowInfo[colInfo[col].gMax].pos;
4638  for (i = s; i <= t; i++) {
4639    row = rowOrder[i];
4640    if (!xy[row][col])
4641      continue;
4642    rowInfo[row].prevG = startVar;
4643    if (rowInfo[row].lNum == 1) {
4644      rowInfo[row].lMin = col;
4645      rowInfo[row].lMax = col;
4646    } else {
4647      if (col == rowInfo[row].lMin) {
4648        for (j = y + 1; j <= colInfo[rowInfo[row].lMax].pos; j++) {
4649          tmpCol = colOrder[j];
4650          if (xy[row][tmpCol]) {
4651            rowInfo[row].lMin = tmpCol;
4652            break;
4653          }
4654        }
4655      } else if (col == rowInfo[row].lMax) {
4656        for (j = y; j >= colInfo[rowInfo[row].lMin].pos; j--) {
4657          tmpCol = colOrder[j];
4658          if (xy[row][tmpCol]) {
4659            rowInfo[row].lMax = tmpCol;
4660            break;
4661          }
4662        }
4663      }
4664    }
4665
4666    if (rowInfo[row].gNum == 1) {
4667      rowInfo[row].gMin = col;
4668      rowInfo[row].gMax = col;
4669    } else {
4670      if (col == rowInfo[row].gMin)
4671        rowInfo[row].gMin = col;
4672      else if (col == rowInfo[row].gMax) {
4673        rowInfo[row].gMax = rowInfo[row].lMax;
4674        if (startVar <= colInfo[rowInfo[row].gMin].pos)
4675          rowInfo[row].gMin = col;
4676      } else if (startVar <= colInfo[rowInfo[row].gMin].pos)
4677        rowInfo[row].gMin = col;
4678    }
4679
4680    if (colInfo[col].lNum) {
4681      if (i == colInfo[col].prevG)
4682        i = rowInfo[colInfo[col].lMin].pos - 1;
4683      else if (i == rowInfo[colInfo[col].lMax].pos)
4684        i = colInfo[col].nextG - 1;
4685    }
4686  }
4687
4688  s = rowInfo[colInfo[col].lMin].pos;
4689  t = rowInfo[colInfo[col].lMax].pos;
4690  for (i = s; i <= t; i++) {
4691    row = rowOrder[i];
4692    if (xy[row][col]) {
4693      rowInfo[row].lNum--;
4694      if (candList) {
4695        if (rowInfo[row].lNum == 0)
4696          SortedListDelete(candList, row);
4697        else if (rowInfo[row].lNum == 1)
4698          SortedListInsert(candList, row, col, colInfo, method);
4699      }
4700    }
4701  }
4702
4703  nMoves++;
4704}
4705
4706
4707/**Function********************************************************************
4708
4709  Synopsis    [Moves a row to the bottom of the active region.]
4710
4711  Description [Moves a row to the bottom of the active region.]
4712
4713  SideEffects []
4714
4715******************************************************************************/
4716static void
4717MoveRowToBottom(char **xy, int x, int startFunc, int lastFunc,
4718                int startVar, int lastVar, RcInfo_t *rowInfo,
4719                RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4720                RcListInfo_t *candList, int method)
4721{
4722  int   i, j, s, t;
4723  int   row, col, tmpRow;
4724
4725  assert(x >= startFunc && x <= lastFunc);
4726
4727  row = rowOrder[x];
4728  if (x != lastFunc) {
4729    /* Change row order */
4730    for (i = x; i < lastFunc; i++) {
4731      rowOrder[i] = rowOrder[i + 1];
4732      rowInfo[rowOrder[i]].pos = i;
4733    }
4734    rowOrder[lastFunc] = row;
4735    rowInfo[row].pos = lastFunc;
4736  }
4737
4738  s = colInfo[rowInfo[row].gMin].pos;
4739  t = colInfo[rowInfo[row].gMax].pos;
4740  for (j = s; j <= t; j++) {
4741    col = colOrder[j];
4742    if (!xy[row][col])
4743      continue;
4744    colInfo[col].nextG = lastFunc;
4745    if (colInfo[col].lNum == 1) {
4746      colInfo[col].lMin = row;
4747      colInfo[col].lMax = row;
4748    } else {
4749      if (row == colInfo[col].lMin) {
4750        for (i = x; i <= rowInfo[colInfo[col].lMax].pos; i++) {
4751          tmpRow = rowOrder[i];
4752          if (xy[tmpRow][col]) {
4753            colInfo[col].lMin = tmpRow;
4754            break;
4755          }
4756        }
4757      } else if (row == colInfo[col].lMax) {
4758        for (i = x - 1; i >= rowInfo[colInfo[col].lMin].pos; i--) {
4759          tmpRow = rowOrder[i];
4760          if (xy[tmpRow][col]) {
4761            colInfo[col].lMax = tmpRow;
4762            break;
4763          }
4764        }
4765      }
4766    }
4767
4768    if (colInfo[col].gNum == 1) {
4769      colInfo[col].gMin = row;
4770      colInfo[col].gMax = row;
4771    } else {
4772      if (row == colInfo[col].gMax)
4773        colInfo[col].gMax = row;
4774      else if (row == colInfo[col].gMin) {
4775        colInfo[col].gMin = colInfo[col].lMin;
4776        if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
4777          colInfo[col].gMax = row;
4778      } else if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
4779        colInfo[col].gMax = row;
4780    }
4781
4782    if (rowInfo[row].lNum) {
4783      if (j == rowInfo[row].prevG)
4784        j = colInfo[rowInfo[row].lMin].pos - 1;
4785      else if (j == colInfo[rowInfo[row].lMax].pos)
4786        j = rowInfo[row].nextG - 1;
4787    }
4788  }
4789
4790  s = colInfo[rowInfo[row].lMin].pos;
4791  t = colInfo[rowInfo[row].lMax].pos;
4792  for (j = s; j <= t; j++) {
4793    col = colOrder[j];
4794    if (xy[row][col]) {
4795      colInfo[col].lNum--;
4796      if (candList) {
4797        if (colInfo[col].lNum == 0)
4798          SortedListDelete(candList, col);
4799        else if (colInfo[col].lNum == 1)
4800          SortedListInsert(candList, col, row, rowInfo, method);
4801      }
4802    }
4803  }
4804
4805  nMoves++;
4806}
4807
4808
4809/**Function********************************************************************
4810
4811  Synopsis    [Moves a column to the tight of the active region.]
4812
4813  Description [Moves a column to the tight of the active region.]
4814
4815  SideEffects []
4816
4817******************************************************************************/
4818static void
4819MoveColToRight(char **xy, int y, int startFunc, int lastFunc,
4820               int startVar, int lastVar, RcInfo_t *rowInfo,
4821               RcInfo_t *colInfo, int *rowOrder, int *colOrder,
4822               RcListInfo_t *candList, int method)
4823{
4824  int   i, j, s, t;
4825  int   row, col, tmpCol;
4826
4827  assert(y >= startVar && y <= lastVar);
4828
4829  col = colOrder[y];
4830  if (y != lastVar) {
4831    /* Change col order */
4832    for (j = y; j < lastVar; j++) {
4833      colOrder[j] = colOrder[j + 1];
4834      colInfo[colOrder[j]].pos = j;
4835    }
4836    colOrder[lastVar] = col;
4837    colInfo[col].pos = lastVar;
4838  }
4839
4840  s = rowInfo[colInfo[col].gMin].pos;
4841  t = rowInfo[colInfo[col].gMax].pos;
4842  for (i = s; i <= t; i++) {
4843    row = rowOrder[i];
4844    if (!xy[row][col])
4845      continue;
4846    rowInfo[row].nextG = lastVar;
4847    if (rowInfo[row].lNum == 1) {
4848      rowInfo[row].lMin = col;
4849      rowInfo[row].lMax = col;
4850    } else {
4851      if (col == rowInfo[row].lMin) {
4852        for (j = y; j <= colInfo[rowInfo[row].lMax].pos; j++) {
4853          tmpCol = colOrder[j];
4854          if (xy[row][tmpCol]) {
4855            rowInfo[row].lMin = tmpCol;
4856            break;
4857          }
4858        }
4859      } else if (col == rowInfo[row].lMax) {
4860        for (j = y - 1; j >= colInfo[rowInfo[row].lMin].pos; j--) {
4861          tmpCol = colOrder[j];
4862          if (xy[row][tmpCol]) {
4863            rowInfo[row].lMax = tmpCol;
4864            break;
4865          }
4866        }
4867      }
4868    }
4869
4870    if (rowInfo[row].gNum == 1) {
4871      rowInfo[row].gMin = col;
4872      rowInfo[row].gMax = col;
4873    } else {
4874      if (col == rowInfo[row].gMax)
4875        rowInfo[row].gMax = col;
4876      else if (col == rowInfo[row].gMin) {
4877        rowInfo[row].gMin = rowInfo[row].lMin;
4878        if (lastVar >= colInfo[rowInfo[row].gMax].pos)
4879          rowInfo[row].gMax = col;
4880      } else if (lastVar >= colInfo[rowInfo[row].gMax].pos)
4881        rowInfo[row].gMax = col;
4882    }
4883
4884    if (colInfo[col].lNum) {
4885      if (i == colInfo[col].prevG)
4886        i = rowInfo[colInfo[col].lMin].pos - 1;
4887      else if (i == rowInfo[colInfo[col].lMax].pos)
4888        i = colInfo[col].nextG - 1;
4889    }
4890  }
4891
4892  s = rowInfo[colInfo[col].lMin].pos;
4893  t = rowInfo[colInfo[col].lMax].pos;
4894  for (i = s; i <= t; i++) {
4895    row = rowOrder[i];
4896    if (xy[row][col]) {
4897      rowInfo[row].lNum--;
4898      if (candList) {
4899        if (rowInfo[row].lNum == 0)
4900          SortedListDelete(candList, row);
4901        else if (rowInfo[row].lNum == 1)
4902          SortedListInsert(candList, row, col, colInfo, method);
4903      }
4904    }
4905  }
4906
4907  nMoves++;
4908}
4909
4910
4911/**Function********************************************************************
4912
4913  Synopsis    [Prints a maxtrix.]
4914
4915  Description [Prints a maxtrix.]
4916
4917  SideEffects []
4918
4919******************************************************************************/
4920static void
4921PrintMatrix(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
4922            RcInfo_t *rowInfo, RcInfo_t *colInfo,
4923            int startFunc, int lastFunc, int startVar, int lastVar)
4924{
4925  int   i, j, x, y;
4926  int   row, col, index;
4927  char  line[2048];
4928  bdd_t *nsVar;
4929
4930  line[nCols] = '\0';
4931  for (x = 0; x < nRows; x++) {
4932    if (startFunc != lastFunc && startVar != lastVar &&
4933        x == startFunc && x != 0) {
4934      for (y = 0; y < nCols; y++) {
4935        if (y == startVar || y == lastVar)
4936          line[y] = '%';
4937        else
4938          line[y] = '=';
4939      }
4940      fprintf(vis_stdout, "%s\n", line);
4941    }
4942    i = rowOrder[x];
4943    for (y = 0; y < nCols; y++) {
4944      j = colOrder[y];
4945      if (xy[i][j])
4946        line[y] = '1';
4947      else
4948        line[y] = '.';
4949    }
4950    fprintf(vis_stdout, "%s\n", line);
4951    if (startFunc != lastFunc && startVar != lastVar &&
4952        x == lastFunc && x < nRows - 1) {
4953      for (y = 0; y < nCols; y++) {
4954        if (y == startVar || y == lastVar)
4955          line[y] = '%';
4956        else
4957          line[y] = '=';
4958      }
4959      fprintf(vis_stdout, "%s\n", line);
4960    }
4961  }
4962  fprintf(vis_stdout, "row order :");
4963  for (x = 0; x < nRows; x++) {
4964    row = rowOrder[x];
4965    fprintf(vis_stdout, " %d(", row);
4966    if (rowInfo[row].data.row.nsVarBddArray) {
4967      for (i = 0; i < array_n(rowInfo[row].data.row.nsVarBddArray); i++) {
4968        nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, i);
4969        index = (int)bdd_top_var_id(nsVar);
4970        if (i == 0)
4971          fprintf(vis_stdout, "%d", index);
4972        else
4973          fprintf(vis_stdout, ",%d", index);
4974      }
4975    }
4976    fprintf(vis_stdout, ")");
4977  }
4978  fprintf(vis_stdout, "\n");
4979  fprintf(vis_stdout, "col order :");
4980  for (y = 0; y < nCols; y++) {
4981    col = colOrder[y];
4982    index = (int)bdd_top_var_id(colInfo[col].data.col.var);
4983    fprintf(vis_stdout, " %d(%d)", col, index);
4984  }
4985  fprintf(vis_stdout, "\n");
4986  fprintf(vis_stdout, "#active rows : %d-%d\n", startFunc, lastFunc);
4987  fprintf(vis_stdout, "#active cols : %d-%d\n", startVar, lastVar);
4988}
4989
4990
4991/**Function********************************************************************
4992
4993  Synopsis    [Prints a matrix with cluster information.]
4994
4995  Description [Prints a matrix with cluster information.]
4996
4997  SideEffects []
4998
4999******************************************************************************/
5000static void
5001PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols,
5002                        int *rowOrder, int *colOrder,
5003                        Img_DirectionType direction)
5004{
5005  int           i, j, x, y;
5006  char          line[2048];
5007  ClusterList_t *list, *tailCluster;
5008
5009  line[nCols] = '\0';
5010  if (direction == Img_Forward_c) {
5011    tailCluster = headCluster;
5012    list = headCluster;
5013    while (list->next) {
5014      tailCluster = list->next;
5015      list = tailCluster;
5016    }
5017    list = tailCluster;
5018    while (list) {
5019      for (x = list->start; x <= list->end; x++) {
5020        i = rowOrder[x];
5021        for (y = 0; y < nCols; y++) {
5022          j = colOrder[y];
5023          if (xy[i][j])
5024            line[y] = '1';
5025          else
5026            line[y] = '.';
5027        }
5028        fprintf(vis_stdout, "%s\n", line);
5029      }
5030      list = list->prev;
5031      if (list) {
5032        for (y = 0; y < nCols; y++)
5033          line[y] = '-';
5034        fprintf(vis_stdout, "%s\n", line);
5035      }
5036    }
5037  } else {
5038    list = headCluster;
5039    while (list) {
5040      for (x = list->start; x <= list->end; x++) {
5041        i = rowOrder[x];
5042        for (y = 0; y < nCols; y++) {
5043          j = colOrder[y];
5044          if (xy[i][j])
5045            line[y] = '1';
5046          else
5047            line[y] = '.';
5048        }
5049        fprintf(vis_stdout, "%s\n", line);
5050      }
5051      list = list->next;
5052      if (list) {
5053        for (y = 0; y < nCols; y++)
5054          line[y] = '-';
5055        fprintf(vis_stdout, "%s\n", line);
5056      }
5057    }
5058  }
5059}
5060
5061
5062/**Function********************************************************************
5063
5064  Synopsis    [Prints cluster information.]
5065
5066  Description [Prints cluster information.]
5067
5068  SideEffects []
5069
5070******************************************************************************/
5071static void
5072PrintClusterMatrix(ClusterList_t *headCluster, int nCols,
5073                   int *colOrder, Img_DirectionType direction)
5074{
5075  int           j, y;
5076  char          line[2048];
5077  ClusterList_t *list, *tailCluster;
5078
5079  line[nCols] = '\0';
5080  if (direction == Img_Forward_c) {
5081    tailCluster = headCluster;
5082    list = headCluster;
5083    while (list->next) {
5084      tailCluster = list->next;
5085      list = tailCluster;
5086    }
5087    list = tailCluster;
5088    while (list) {
5089      for (y = 0; y < nCols; y++) {
5090        j = colOrder[y];
5091        if (list->supports[j])
5092          line[y] = '1';
5093        else
5094          line[y] = '.';
5095      }
5096      fprintf(vis_stdout, "%s\n", line);
5097      list = list->prev;
5098      if (list) {
5099        for (y = 0; y < nCols; y++)
5100          line[y] = '-';
5101        fprintf(vis_stdout, "%s\n", line);
5102      }
5103    }
5104  } else {
5105    list = headCluster;
5106    while (list) {
5107      for (y = 0; y < nCols; y++) {
5108        j = colOrder[y];
5109        if (list->supports[j])
5110          line[y] = '1';
5111        else
5112          line[y] = '.';
5113      }
5114      fprintf(vis_stdout, "%s\n", line);
5115      list = list->next;
5116      if (list) {
5117        for (y = 0; y < nCols; y++)
5118          line[y] = '-';
5119        fprintf(vis_stdout, "%s\n", line);
5120      }
5121    }
5122  }
5123}
5124
5125
5126/**Function********************************************************************
5127
5128  Synopsis    [Checks a matrix for sanity.]
5129
5130  Description [Checks a matrix for sanity.]
5131
5132  SideEffects []
5133
5134******************************************************************************/
5135static void
5136CheckMatrix(char **xy, SccList_t *sccList, int nRows, int nCols,
5137            RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
5138            int startFunc, int lastFunc, int startVar, int lastVar, int local)
5139{
5140  int   i, j, x, y;
5141  int   lMin, lMax, gMin, gMax, lNum, gNum, prevG, nextG;
5142  int   error = 0;
5143
5144  for (x = 0; x < nRows; x++) {
5145    i = rowOrder[x];
5146    if (x != rowInfo[i].pos) {
5147      fprintf(vis_stderr, "Error : wrong rowOrder (%d != %d) in Row %d\n",
5148             x, rowInfo[i].pos, x);
5149      error = 1;
5150    }
5151
5152    lMin = gMin = nCols;
5153    lMax = gMax = -1;
5154    lNum = gNum = 0;
5155    prevG = -1;
5156    nextG = nCols;
5157
5158    for (y = 0; y < nCols; y++) {
5159      j = colOrder[y];
5160      if (xy[i][j]) {
5161        gNum++;
5162        if (y < gMin)
5163          gMin = y;
5164        if (y > gMax)
5165          gMax = y;
5166        if (local) {
5167          if (x >= startFunc && x <= lastFunc &&
5168              y >= startVar && y <= lastVar) {
5169            if (y < lMin)
5170              lMin = y;
5171            if (y > lMax)
5172              lMax = y;
5173            lNum++;
5174          }
5175          if (!sccList ||
5176              (x >= sccList->startFunc && x <= sccList->lastFunc)) {
5177            if (y < startVar)
5178              prevG = y;
5179            if (y > lastVar && nextG == nCols)
5180              nextG = y;
5181          }
5182        }
5183      }
5184    }
5185    if (gNum != rowInfo[i].gNum) {
5186      fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Row %d\n",
5187             gNum, rowInfo[i].gNum, x);
5188      error = 1;
5189    }
5190    if (gNum > 0) {
5191      if (gMin != colInfo[rowInfo[i].gMin].pos) {
5192        fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Row %d\n",
5193               gMin, colInfo[rowInfo[i].gMin].pos, x);
5194        error = 1;
5195      }
5196      if (gMax != colInfo[rowInfo[i].gMax].pos) {
5197        fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Row %d\n",
5198               gMax, colInfo[rowInfo[i].gMax].pos, x);
5199        error = 1;
5200      }
5201    }
5202    if (local) {
5203      if (x >= startFunc && x <= lastFunc &&
5204          lNum != rowInfo[i].lNum) {
5205        fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Row %d\n",
5206               lNum, rowInfo[i].lNum, x);
5207        error = 1;
5208      }
5209      if (x >= startFunc && x <= lastFunc && lMin < nCols &&
5210          lMin != colInfo[rowInfo[i].lMin].pos) {
5211        fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Row %d\n",
5212               lMin, colInfo[rowInfo[i].lMin].pos, x);
5213        error = 1;
5214      }
5215      if (x >= startFunc && x <= lastFunc && lMax > -1 &&
5216          lMax != colInfo[rowInfo[i].lMax].pos) {
5217        fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Row %d\n",
5218               lMax, colInfo[rowInfo[i].lMax].pos, x);
5219        error = 1;
5220      }
5221      if (!sccList || (x >= sccList->startFunc && x <= sccList->lastFunc)) {
5222        if (prevG != rowInfo[i].prevG) {
5223          fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Row %d\n",
5224                  prevG, rowInfo[i].prevG, x);
5225          error = 1;
5226        }
5227        if (nextG != rowInfo[i].nextG) {
5228          fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Row %d\n",
5229                  nextG, rowInfo[i].nextG, x);
5230          error = 1;
5231        }
5232      }
5233    }
5234  }
5235
5236  for (y = 0; y < nCols; y++) {
5237    j = colOrder[y];
5238    if (y != colInfo[j].pos) {
5239      fprintf(vis_stderr, "Error : wrong colOrder (%d != %d) in Col %d\n",
5240             y, colInfo[y].pos, y);
5241      error = 1;
5242    }
5243
5244    lMin = gMin = nRows;
5245    lMax = gMax = -1;
5246    lNum = gNum = 0;
5247    prevG = -1;
5248    nextG = nRows;
5249
5250    for (x = 0; x < nRows; x++) {
5251      i = rowOrder[x];
5252      if (xy[i][j]) {
5253        gNum++;
5254        if (x < gMin)
5255          gMin = x;
5256        if (x > gMax)
5257          gMax = x;
5258        if (local) {
5259          if (x >= startFunc && x <= lastFunc &&
5260              y >= startVar && y <= lastVar) {
5261            if (x < lMin)
5262              lMin = x;
5263            if (x > lMax)
5264              lMax = x;
5265            lNum++;
5266          }
5267          if (!sccList ||
5268              (y >= sccList->startVar && y <= sccList->lastVar)) {
5269            if (x < startFunc)
5270              prevG = x;
5271            if (x > lastFunc && nextG == nRows)
5272              nextG = x;
5273          }
5274        }
5275      }
5276    }
5277    if (gNum != colInfo[j].gNum) {
5278      fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Col %d\n",
5279             gNum, colInfo[j].gNum, y);
5280      error = 1;
5281    }
5282    if (gNum > 0) {
5283      if (gMin != rowInfo[colInfo[j].gMin].pos) {
5284        fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Col %d\n",
5285               gMin, rowInfo[colInfo[j].gMin].pos, y);
5286        error = 1;
5287      }
5288      if (gMax != rowInfo[colInfo[j].gMax].pos) {
5289        fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Col %d\n",
5290               gMax, rowInfo[colInfo[j].gMax].pos, y);
5291        error = 1;
5292      }
5293    }
5294    if (local) {
5295      if (y >= startVar && y <= lastVar &&
5296          lNum != colInfo[j].lNum) {
5297        fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Col %d\n",
5298               lNum, colInfo[j].lNum, y);
5299        error = 1;
5300      }
5301      if (y >= startVar && y <= lastVar && lMin < nRows &&
5302          lMin != rowInfo[colInfo[j].lMin].pos) {
5303        fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Col %d\n",
5304               lMin, rowInfo[colInfo[j].lMin].pos, y);
5305        error = 1;
5306      }
5307      if (y >= startVar && y <= lastVar && lMax > -1 &&
5308          lMax != rowInfo[colInfo[j].lMax].pos) {
5309        fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Col %d\n",
5310               lMax, rowInfo[colInfo[j].lMax].pos, y);
5311        error = 1;
5312      }
5313      if (!sccList || (y >= sccList->startVar && y <= sccList->lastVar)) {
5314        if (prevG != colInfo[j].prevG) {
5315          fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Col %d\n",
5316                  prevG, colInfo[j].prevG, y);
5317          error = 1;
5318        }
5319        if (nextG != colInfo[j].nextG) {
5320          fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Col %d\n",
5321                  nextG, colInfo[j].nextG, y);
5322          error = 1;
5323        }
5324      }
5325    }
5326  }
5327
5328  assert(!error);
5329}
5330
5331
5332/**Function********************************************************************
5333
5334  Synopsis    [Checks cluster for sanity.]
5335
5336  Description [Checks cluster for sanity.]
5337
5338  SideEffects []
5339
5340******************************************************************************/
5341static void
5342CheckCluster(ClusterList_t *headCluster, int nCols,
5343                RcInfo_t *colInfo, int *colOrder)
5344{
5345  int   j, y, n;
5346  int   gMin, gMax, gNum;
5347  int   error = 0;
5348  ClusterList_t *list;
5349
5350  n = 0;
5351  list = headCluster;
5352  while (list) {
5353    gMin = nCols;
5354    gMax = -1;
5355    gNum = 0;
5356
5357    for (y = 0; y < nCols; y++) {
5358      j = colOrder[y];
5359      if (list->supports[j]) {
5360        gNum++;
5361        if (y < gMin)
5362          gMin = y;
5363        if (y > gMax)
5364          gMax = y;
5365      }
5366    }
5367    if (gNum != list->nSupports) {
5368      fprintf(vis_stderr, "Error : wrong nSupports (%d != %d) in Cluster %d\n",
5369             gNum, list->nSupports, n);
5370      error = 1;
5371    }
5372    if (gNum > 0) {
5373      if (gMin != colInfo[list->minCol].pos) {
5374        fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Cluster %d\n",
5375               gMin, colInfo[list->minCol].pos, n);
5376        error = 1;
5377      }
5378      if (gMax != colInfo[list->maxCol].pos) {
5379        fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Cluster %d\n",
5380               gMax, colInfo[list->maxCol].pos, n);
5381        error = 1;
5382      }
5383    }
5384    n++;
5385    list = list->next;
5386  }
5387
5388  assert(!error);
5389}
5390
5391
5392/**Function********************************************************************
5393
5394  Synopsis    [Writes a matrix to a file.]
5395
5396  Description [Writes a matrix to a file.]
5397
5398  SideEffects []
5399
5400******************************************************************************/
5401static void
5402WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder,
5403            int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo)
5404{
5405  int   x, y;
5406  int   row, col;
5407
5408  for (x = 0; x < nRows; x++) {
5409    row = rowOrder[x];
5410    for (y = 0; y < nCols; y++) {
5411      col = colOrder[y];
5412      if (xy[row][col])
5413        fprintf(fout, "%d %d %d\n", y, x, colInfo[col].data.col.type);
5414    }
5415  }
5416}
5417
5418
5419/**Function********************************************************************
5420
5421  Synopsis    [Prints a row.]
5422
5423  Description [Prints a row.]
5424
5425  SideEffects []
5426
5427******************************************************************************/
5428static void
5429PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
5430         int from, int to)
5431{
5432  int   x, y, row, col;
5433
5434  for (x = from; x <= to; x++) {
5435    row = rowOrder[x];
5436    fprintf(vis_stdout, "[%d]%d :", x, row);
5437    for (y = 0; y < nCols; y++) {
5438      col = colOrder[y];
5439      if (xy[row][col])
5440        fprintf(vis_stdout, " %d(%d)", y, col);
5441    }
5442    fprintf(vis_stdout, "\n");
5443  }
5444}
5445
5446
5447/**Function********************************************************************
5448
5449  Synopsis    [Prints a column.]
5450
5451  Description [Prints a column.]
5452
5453  SideEffects []
5454
5455******************************************************************************/
5456static void
5457PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
5458         int from, int to)
5459{
5460  int   x, y, row, col;
5461
5462  for (y = from; y <= to; y++) {
5463    col = colOrder[y];
5464    fprintf(vis_stdout, "[%d]%d :", y, col);
5465    for (x = 0; x < nRows; x++) {
5466      row = rowOrder[x];
5467      if (xy[row][col])
5468        fprintf(vis_stdout, " %d(%d)", x, row);
5469    }
5470    fprintf(vis_stdout, "\n");
5471  }
5472}
5473
5474
5475/**Function********************************************************************
5476
5477  Synopsis    [Allocates a list for sorting.]
5478
5479  Description [Allocates a list for sorting.]
5480
5481  SideEffects []
5482
5483******************************************************************************/
5484static RcListInfo_t *
5485SortedListAlloc(void)
5486{
5487  RcListInfo_t  *listInfo;
5488
5489  listInfo = ALLOC(RcListInfo_t, 1);
5490  memset(listInfo, 0, sizeof(RcListInfo_t));
5491  listInfo->table = st_init_table(st_numcmp, st_numhash);
5492  return(listInfo);
5493}
5494
5495
5496/**Function********************************************************************
5497
5498  Synopsis    [Frees a list used for sorting.]
5499
5500  Description [Frees a list used for sorting.]
5501
5502  SideEffects []
5503
5504******************************************************************************/
5505static void
5506SortedListFree(RcListInfo_t *candList)
5507{
5508  RcList_t      *candidate, *next;
5509
5510  candidate = candList->head;
5511  while (candidate) {
5512    next = candidate->next;
5513    FREE(candidate);
5514    candidate = next;
5515  }
5516  st_free_table(candList->table);
5517  FREE(candList);
5518}
5519
5520
5521/**Function********************************************************************
5522
5523  Synopsis    [Inserts a list to the sorting list.]
5524
5525  Description [Inserts a list to the sorting list.]
5526
5527  SideEffects []
5528
5529******************************************************************************/
5530static void
5531SortedListInsert(RcListInfo_t *candList, int index,
5532                 int otherIndex, RcInfo_t *otherInfo, int method)
5533{
5534  RcList_t      *candidate, *cur;
5535  int           lNum, gNum, diffH, diffT;
5536
5537  candidate = ALLOC(RcList_t, 1);
5538  candidate->index = index;
5539  candidate->otherIndex = otherIndex;
5540  st_insert(candList->table, (char *)(long)index, (char *)candidate);
5541
5542  if (candList->num == 0) {
5543    candidate->next = NIL(RcList_t);
5544    candidate->prev = NIL(RcList_t);
5545    candList->cur = candidate;
5546    candList->head = candidate;
5547    candList->tail = candidate;
5548    candList->num = 1;
5549    candList->maxNum = 1;
5550    return;
5551  }
5552
5553  candList->num++;
5554  if (candList->num > candList->maxNum)
5555    candList->maxNum = candList->num;
5556
5557  if (method == 1) {
5558    diffH = abs(index - candList->head->index);
5559    diffT = abs(index - candList->tail->index);
5560
5561    if (diffH < diffT) {
5562      cur = candList->head;
5563      while (cur) {
5564        if (index < cur->index) {
5565          candidate->next = cur;
5566          candidate->prev = cur->prev;
5567          if (cur->prev)
5568            cur->prev->next = candidate;
5569          cur->prev = candidate;
5570          if (cur == candList->head)
5571            candList->head = candidate;
5572          break;
5573        }
5574        cur = cur->next;
5575      }
5576      if (!cur) {
5577        candidate->next = NIL(RcList_t);
5578        candidate->prev = candList->tail;
5579        candList->tail->next = candidate;
5580        candList->tail = candidate;
5581      }
5582    } else {
5583      cur = candList->tail;
5584      while (cur) {
5585        if (index > cur->index) {
5586          candidate->next = cur->next;
5587          if (cur->next)
5588            cur->next->prev = candidate;
5589          candidate->prev = cur;
5590          cur->next = candidate;
5591          if (cur == candList->tail)
5592            candList->tail = candidate;
5593          break;
5594        }
5595        cur = cur->prev;
5596      }
5597      if (!cur) {
5598        candidate->next = candList->head;
5599        candidate->prev = NIL(RcList_t);
5600        candList->head->prev = candidate;
5601        candList->head = candidate;
5602      }
5603    }
5604
5605    if (candList->cur) {
5606      if (candList->cur->index == candList->curIndex)
5607        return;
5608      else if (candList->cur->index > candList->curIndex) {
5609        cur = candList->cur->prev;
5610        while (cur) {
5611          if (cur->index <= candList->curIndex)
5612            break;
5613          candList->cur = cur;
5614          cur = cur->prev;
5615        }
5616      } else {
5617        if (candidate->index > candList->curIndex)
5618          candList->cur = candidate;
5619        else
5620          candList->cur = candList->head;
5621      }
5622    } else
5623      candList->cur = candList->head;
5624  } else if (method == 2) {
5625    lNum = otherInfo[otherIndex].lNum;
5626    gNum = otherInfo[otherIndex].gNum;
5627    diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
5628    diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
5629
5630    if (diffH < diffT) {
5631      cur = candList->head;
5632      while (cur) {
5633        if (lNum < otherInfo[cur->otherIndex].lNum ||
5634            (lNum == otherInfo[cur->otherIndex].lNum &&
5635             (gNum < otherInfo[cur->otherIndex].gNum ||
5636              (gNum == otherInfo[cur->otherIndex].gNum &&
5637                index < cur->index)))) {
5638          candidate->next = cur;
5639          candidate->prev = cur->prev;
5640          if (cur->prev)
5641            cur->prev->next = candidate;
5642          cur->prev = candidate;
5643          if (cur == candList->head)
5644            candList->head = candidate;
5645          break;
5646        }
5647        cur = cur->next;
5648      }
5649      if (!cur) {
5650        candidate->next = NIL(RcList_t);
5651        candidate->prev = candList->tail;
5652        candList->tail->next = candidate;
5653        candList->tail = candidate;
5654      }
5655    } else {
5656      cur = candList->tail;
5657      while (cur) {
5658        if (lNum > otherInfo[cur->otherIndex].lNum ||
5659            (lNum == otherInfo[cur->otherIndex].lNum &&
5660             (gNum > otherInfo[cur->otherIndex].gNum ||
5661              (gNum == otherInfo[cur->otherIndex].gNum &&
5662                index > cur->index)))) {
5663          candidate->next = cur->next;
5664          if (cur->next)
5665            cur->next->prev = candidate;
5666          candidate->prev = cur;
5667          cur->next = candidate;
5668          if (cur == candList->tail)
5669            candList->tail = candidate;
5670          break;
5671        }
5672        cur = cur->prev;
5673      }
5674      if (!cur) {
5675        candidate->next = candList->head;
5676        candidate->prev = NIL(RcList_t);
5677        candList->head->prev = candidate;
5678        candList->head = candidate;
5679      }
5680    }
5681  } else if (method == 3) {
5682    lNum = otherInfo[otherIndex].lNum;
5683    gNum = otherInfo[otherIndex].gNum;
5684    diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
5685    diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
5686
5687    if (diffH < diffT) {
5688      cur = candList->head;
5689      while (cur) {
5690        if (lNum < otherInfo[cur->otherIndex].lNum ||
5691            (lNum == otherInfo[cur->otherIndex].lNum &&
5692             (gNum > otherInfo[cur->otherIndex].gNum ||
5693              (gNum == otherInfo[cur->otherIndex].gNum &&
5694                otherInfo[index].pos < otherInfo[cur->index].pos)))) {
5695          candidate->next = cur;
5696          candidate->prev = cur->prev;
5697          if (cur->prev)
5698            cur->prev->next = candidate;
5699          cur->prev = candidate;
5700          if (cur == candList->head)
5701            candList->head = candidate;
5702          break;
5703        }
5704        cur = cur->next;
5705      }
5706      if (!cur) {
5707        candidate->next = NIL(RcList_t);
5708        candidate->prev = candList->tail;
5709        candList->tail->next = candidate;
5710        candList->tail = candidate;
5711      }
5712    } else {
5713      cur = candList->tail;
5714      while (cur) {
5715        if (lNum > otherInfo[cur->otherIndex].lNum ||
5716            (lNum == otherInfo[cur->otherIndex].lNum &&
5717             (gNum < otherInfo[cur->otherIndex].gNum ||
5718              (gNum == otherInfo[cur->otherIndex].gNum &&
5719                otherInfo[index].pos > otherInfo[cur->index].pos)))) {
5720          candidate->next = cur->next;
5721          if (cur->next)
5722            cur->next->prev = candidate;
5723          candidate->prev = cur;
5724          cur->next = candidate;
5725          if (cur == candList->tail)
5726            candList->tail = candidate;
5727          break;
5728        }
5729        cur = cur->prev;
5730      }
5731      if (!cur) {
5732        candidate->next = candList->head;
5733        candidate->prev = NIL(RcList_t);
5734        candList->head->prev = candidate;
5735        candList->head = candidate;
5736      }
5737    }
5738  } else if (method == 4) {
5739    lNum = otherInfo[index].lNum;
5740    cur = candList->tail;
5741    while (cur) {
5742      if (cur->otherIndex > 1 ||
5743          (cur->otherIndex == 1 && otherInfo[cur->index].lNum > lNum) ||
5744          (cur->otherIndex == 1 && otherInfo[cur->index].lNum == lNum &&
5745           otherInfo[index].pos > otherInfo[cur->index].pos)) {
5746        candidate->next = cur->next;
5747        if (cur->next)
5748          cur->next->prev = candidate;
5749        candidate->prev = cur;
5750        cur->next = candidate;
5751        if (cur == candList->tail)
5752          candList->tail = candidate;
5753        break;
5754      }
5755      cur = cur->prev;
5756    }
5757    if (!cur) {
5758      candidate->next = candList->head;
5759      candidate->prev = NIL(RcList_t);
5760      candList->head->prev = candidate;
5761      candList->head = candidate;
5762    }
5763  } else {
5764    fprintf(vis_stderr, "** mlp error: invalid sort mode %d\n", method);
5765  }
5766
5767  candList->cur = candList->head;
5768}
5769
5770
5771/**Function********************************************************************
5772
5773  Synopsis    [Deletes a list from the sorting list.]
5774
5775  Description [Deletes a list from the sorting list.]
5776
5777  SideEffects []
5778
5779******************************************************************************/
5780static void
5781SortedListDelete(RcListInfo_t *candList, int index)
5782{
5783  RcList_t      *candidate;
5784  long          lindex = (long) index;
5785
5786  if (st_lookup(candList->table, (char *)lindex, &candidate)) {
5787    if (candidate == candList->head)
5788      candList->head = candidate->next;
5789    else
5790      candidate->prev->next = candidate->next;
5791    if (candidate == candList->tail)
5792      candList->tail = candidate->prev;
5793    else
5794      candidate->next->prev = candidate->prev;
5795    if (candidate == candList->cur) {
5796      if (candidate->next)
5797        candList->cur = candidate->next;
5798      else
5799        candList->cur = candList->head;
5800    }
5801    st_delete(candList->table, &lindex, NULL);
5802    candList->num--;
5803    FREE(candidate);
5804  }
5805}
5806
5807
5808/**Function********************************************************************
5809
5810  Synopsis    [Moves a list in the sorting list.]
5811
5812  Description [Moves a list in the sorting list.]
5813
5814  SideEffects []
5815
5816******************************************************************************/
5817static void
5818SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method)
5819{
5820  RcList_t      *cur, *prev, *left, *right;
5821
5822  if (st_lookup(candList->table, (char *)(long)index, &cur)) {
5823    if (method == 1) {
5824    } else if (method == 2) {
5825    } else if (method == 3) {
5826      while (cur != candList->head) {
5827        prev = cur->prev;
5828        if (info[prev->index].lNum < info[cur->index].lNum ||
5829            (info[prev->index].lNum == info[cur->index].lNum &&
5830             (info[prev->index].gNum > info[cur->index].gNum ||
5831              (info[prev->index].gNum == info[cur->index].gNum &&
5832                info[prev->index].pos < info[cur->index].pos)))) {
5833          break;
5834        }
5835
5836        /* swap */
5837        if (prev == candList->head)
5838          candList->head = cur;
5839        if (cur == candList->tail)
5840          candList->tail = prev;
5841        left = prev->prev;
5842        right = cur->next;
5843        if (left)
5844          left->next = cur;
5845        cur->next = prev;
5846        prev->next = right;
5847        if (right)
5848          right->prev = prev;
5849        prev->prev = cur;
5850        cur->prev = left;
5851      }
5852    } else if (method == 4) {
5853      while (cur != candList->head) {
5854        prev = cur->prev;
5855        if (prev->otherIndex > cur->otherIndex ||
5856            (prev->otherIndex == cur->otherIndex &&
5857             (info[prev->index].lNum > info[cur->index].lNum ||
5858              (info[prev->index].lNum == info[cur->index].lNum &&
5859                info[prev->index].pos < info[cur->index].pos)))) {
5860          break;
5861        }
5862
5863        /* swap */
5864        if (prev == candList->head)
5865          candList->head = cur;
5866        if (cur == candList->tail)
5867          candList->tail = prev;
5868        left = prev->prev;
5869        right = cur->next;
5870        if (left)
5871          left->next = cur;
5872        cur->next = prev;
5873        prev->next = right;
5874        if (right)
5875          right->prev = prev;
5876        prev->prev = cur;
5877        cur->prev = left;
5878      }
5879    }
5880  }
5881}
5882
5883
5884/**Function********************************************************************
5885
5886  Synopsis    [Checks the sorting list for sanity.]
5887
5888  Description [Checks the sorting list for sanity.]
5889
5890  SideEffects []
5891
5892******************************************************************************/
5893static void
5894CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method)
5895{
5896  RcList_t      *cur, *next, *candidate;
5897  int           error = 0;
5898  int           num = 0;
5899
5900  cur = candList->head;
5901  while (cur) {
5902    num++;
5903    next = cur->next;
5904    if (next) {
5905      if (next->prev != cur) {
5906        error++;
5907        if (next->prev) {
5908          fprintf(vis_stderr, "Error : prev of %d is not %d (!= %d) in list\n",
5909                 next->index, cur->index, next->prev->index);
5910        } else {
5911          fprintf(vis_stderr, "Error : prev of %d is not %d (!= nil) in list\n",
5912                 next->index, cur->index);
5913        }
5914      }
5915      if (method == 1) {
5916      } else if (method == 2) {
5917      } else if (method == 3) {
5918        if (info[cur->index].lNum > info[next->index].lNum) {
5919          error++;
5920          fprintf(vis_stderr,
5921                  "Error : cur(%d) lNum(%d) > next(%d) lNum(%d) in row list\n",
5922                  cur->index, info[cur->index].lNum,
5923                  next->index, info[next->index].lNum);
5924        } else if (info[cur->index].lNum == info[next->index].lNum &&
5925                   info[cur->index].gNum < info[next->index].gNum) {
5926          error++;
5927          fprintf(vis_stderr,
5928                  "Error : cur(%d) gNum(%d) < next(%d) gNum(%d) in row list\n",
5929                  cur->index, info[cur->index].gNum,
5930                  next->index, info[next->index].gNum);
5931        } else if (info[cur->index].lNum == info[next->index].lNum &&
5932                   info[cur->index].gNum == info[next->index].gNum &&
5933                   info[cur->index].pos > info[next->index].pos) {
5934          error++;
5935          fprintf(vis_stderr,
5936                  "Error : cur(%d) pos(%d) > next(%d) pos(%d) in row list\n",
5937                  cur->index, info[cur->index].pos,
5938                  next->index, info[next->index].pos);
5939        }
5940      } else if (method == 4) {
5941        if (cur->otherIndex < next->otherIndex) {
5942          error++;
5943          fprintf(vis_stderr, 
5944              "Error : cur(%d) length(%d) < next(%d) length(%d) in col list\n",
5945                  cur->index, cur->otherIndex, next->index, next->otherIndex);
5946        } else if (cur->otherIndex == next->otherIndex &&
5947                   info[cur->index].lNum < info[next->index].lNum) {
5948          error++;
5949          fprintf(vis_stderr,
5950                  "Error : cur(%d) lNum(%d) < next(%d) lNum(%d) in col list\n",
5951                  cur->index, info[cur->index].lNum,
5952                  next->index, info[next->index].lNum);
5953        } else if (cur->otherIndex == next->otherIndex &&
5954                   info[cur->index].lNum == info[next->index].lNum &&
5955                   info[cur->index].pos > info[next->index].pos) {
5956          error++;
5957          fprintf(vis_stderr,
5958                  "Error : cur(%d) pos(%d) > next(%d) pos(%d) in col list\n",
5959                  cur->index, info[cur->index].pos,
5960                  next->index, info[next->index].pos);
5961        }
5962      }
5963    } else {
5964      if (cur != candList->tail) {
5965        error++;
5966        if (candList->tail) {
5967          fprintf(vis_stderr, "Error : different tail in list (%d != %d)\n",
5968                 cur->index, candList->tail->index);
5969        } else {
5970          fprintf(vis_stderr, "Error : different tail in list (%d != nil)\n",
5971                cur->index);
5972        }
5973      }
5974    }
5975    if (!st_lookup(candList->table, (char *)(long)cur->index, &candidate)) {
5976      error++;
5977      fprintf(vis_stderr, "Error : index %d not in table\n", cur->index);
5978    }
5979    cur = next;
5980  }
5981  if (num != candList->num) {
5982    error++;
5983    fprintf(vis_stderr,
5984            "Error : different number of elements in list (%d != %d)\n",
5985            num, candList->num);
5986  }
5987  if (num != st_count(candList->table)) {
5988    error++;
5989    fprintf(vis_stderr,
5990            "Error : different number of elements in table (%d != %d)\n",
5991            num, st_count(candList->table));
5992  }
5993  assert(!error);
5994}
5995
5996
5997/**Function********************************************************************
5998
5999  Synopsis    [Clusters on the ordered bits.]
6000
6001  Description [Clusters on the ordered bits.]
6002
6003  SideEffects []
6004
6005******************************************************************************/
6006static void
6007MlpCluster(mdd_manager *mddManager, char **xy, int nRows, int nCols,
6008                int nActiveRows, int nActiveCols,
6009                int *nClusterRows, int *nClusterCols,
6010                int *rowOrder, int *colOrder,
6011                RcInfo_t *rowInfo, RcInfo_t *colInfo,
6012                array_t *clusterArray, array_t *arraySmoothVarBddArray,
6013                Img_DirectionType direction, int *cRowOrder,
6014                array_t *nsVarBddArray, int *sccBorder,
6015                int *varPos, ImgTrmOption_t *option)
6016{
6017  int                   i, j, row, col;
6018  int                   ncRows, ncCols;
6019  int                   index, qVarPos;
6020  int                   s1, t1, s2;
6021  array_t               *smoothVarBddArray;
6022  mdd_t                 *nsVar, *relation, *cluster, *tempCluster;
6023  ClusterList_t         *list, *headCluster, *tailCluster, *nextList, *prevList;
6024  ClusterSortedList_t   *clusterSortedList;
6025  long                  initialTime, finalTime;
6026  int                   moveFlag = 1;
6027  array_t               *nonAppearingVarBddArray;
6028  char                  *existFlag;
6029  array_t               *supportArray, *tmpArray;
6030  int                   nVars = bdd_num_vars(mddManager);
6031  mdd_t                 *one;
6032
6033  if (option->mlpVerbosity)
6034    initialTime = util_cpu_time();
6035  else
6036    initialTime = 0;
6037
6038  ncCols = nActiveCols;
6039  headCluster = NIL(ClusterList_t);
6040  tailCluster = NIL(ClusterList_t);
6041  clusterSortedList = NIL(ClusterSortedList_t);
6042  if (option->mlpCluster == 0) {
6043    if (direction == Img_Forward_c) {
6044      for (i = nActiveRows - 1; i >= 0;) {
6045        row = rowOrder[i];
6046
6047        list = ALLOC(ClusterList_t, 1);
6048        memset(list, 0, sizeof(ClusterList_t));
6049        list->flag = 3;
6050        list->start = i;
6051        list->end = i;
6052        list->supports = ALLOC(char, nCols);
6053        memcpy(list->supports, xy[row], sizeof(char) * nCols);
6054        list->minCol = rowInfo[row].gMin;
6055        list->maxCol = rowInfo[row].gMax;
6056        list->nSupports = MlpCountSupport(list, colOrder, ncCols);
6057        list->product = bdd_dup(rowInfo[row].data.row.func);
6058        list->nQuantifyVars = 0;
6059        list->affinity = 0.0;
6060        if (rowInfo[row].data.row.nsVarBddArray)
6061          list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
6062        else
6063          list->nsVarBddArray = NIL(array_t);
6064
6065        if (headCluster)
6066          tailCluster->next = list;
6067        else
6068          headCluster = list;
6069        list->next = NIL(ClusterList_t);
6070        list->prev = tailCluster;
6071        tailCluster = list;
6072
6073        i--;
6074
6075        if (sccBorder && sccBorder[i + 1] == 1)
6076          continue;
6077        if (bdd_size(list->product) >= option->clusterSize)
6078          continue;
6079
6080        while (i >= 0) {
6081          row = rowOrder[i];
6082          relation = rowInfo[row].data.row.func;
6083          if (bdd_size(list->product) >= option->clusterSize)
6084            break;
6085          cluster = bdd_and(list->product, relation, 1, 1);
6086          if (bdd_size(cluster) <= option->clusterSize) {
6087            mdd_free(list->product);
6088            list->product = cluster;
6089            list->start = i;
6090
6091            if (list->nsVarBddArray) {
6092              array_append(list->nsVarBddArray,
6093                rowInfo[row].data.row.nsVarBddArray);
6094            }
6095
6096            list->nSupports = 0;
6097            list->minCol = nActiveCols;
6098            list->maxCol = -1;
6099            s1 = nActiveCols;
6100            t1 = -1;
6101            supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
6102            for (j = 0; j < array_n(supportArray); j++) {
6103              index = array_fetch(int, supportArray, j);
6104              if (varPos[index] == 0) {
6105                if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
6106                  continue;
6107              }
6108              index = varPos[index];
6109              list->supports[index] = 1;
6110              list->nSupports++;
6111              s2 = colInfo[index].pos;
6112              if (s2 < s1) {
6113                s1 = s2;
6114                list->minCol = index;
6115              }
6116              if (s2 > t1) {
6117                t1 = s2;
6118                list->maxCol = index;
6119              }
6120            }
6121            array_free(supportArray);
6122
6123            i--;
6124            if (option->mlpDebug)
6125              CheckCluster(headCluster, ncCols, colInfo, colOrder);
6126          } else {
6127            mdd_free(cluster);
6128            break;
6129          }
6130        }
6131
6132        ncCols = RemoveLocalVarsInCluster(mddManager, xy,
6133                                            list, nActiveRows, ncCols,
6134                                            rowInfo, colInfo,
6135                                            rowOrder, colOrder,
6136                                            moveFlag, option);
6137      }
6138    } else {
6139      for (i = 0; i < nActiveRows;) {
6140        row = rowOrder[i];
6141
6142        list = ALLOC(ClusterList_t, 1);
6143        memset(list, 0, sizeof(ClusterList_t));
6144        list->flag = 3;
6145        list->start = i;
6146        list->end = i;
6147        list->supports = ALLOC(char, nCols);
6148        memcpy(list->supports, xy[row], sizeof(char) * nCols);
6149        list->minCol = rowInfo[row].gMin;
6150        list->maxCol = rowInfo[row].gMax;
6151        list->nSupports = MlpCountSupport(list, colOrder, ncCols);
6152        list->product = bdd_dup(rowInfo[row].data.row.func);
6153        list->nQuantifyVars = 0;
6154        list->affinity = 0.0;
6155        if (rowInfo[row].data.row.nsVarBddArray)
6156          list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
6157        else
6158          list->nsVarBddArray = NIL(array_t);
6159
6160        if (headCluster)
6161          tailCluster->next = list;
6162        else
6163          headCluster = list;
6164        list->next = NIL(ClusterList_t);
6165        list->prev = tailCluster;
6166        tailCluster = list;
6167
6168        i++;
6169
6170        if (sccBorder && sccBorder[i - 1] == 2)
6171          continue;
6172        if (bdd_size(list->product) >= option->clusterSize)
6173          continue;
6174
6175        while (i < nActiveRows) {
6176          row = rowOrder[i];
6177          relation = rowInfo[row].data.row.func;
6178          if (bdd_size(list->product) >= option->clusterSize)
6179            break;
6180          cluster = bdd_and(list->product, relation, 1, 1);
6181          if (bdd_size(cluster) <= option->clusterSize) {
6182            mdd_free(list->product);
6183            list->product = cluster;
6184            list->end = i;
6185
6186            if (list->nsVarBddArray) {
6187              array_append(list->nsVarBddArray,
6188                rowInfo[row].data.row.nsVarBddArray);
6189            }
6190
6191            list->nSupports = 0;
6192            list->minCol = nActiveCols;
6193            list->maxCol = -1;
6194            s1 = nActiveCols;
6195            t1 = -1;
6196            supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
6197            for (j = 0; j < array_n(supportArray); j++) {
6198              index = array_fetch(int, supportArray, j);
6199              if (varPos[index] == 0) {
6200                if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
6201                  continue;
6202              }
6203              index = varPos[index];
6204              list->supports[index] = 1;
6205              list->nSupports++;
6206              s2 = colInfo[index].pos;
6207              if (s2 < s1) {
6208                s1 = s2;
6209                list->minCol = index;
6210              }
6211              if (s2 > t1) {
6212                t1 = s2;
6213                list->maxCol = index;
6214              }
6215            }
6216            array_free(supportArray);
6217
6218            i++;
6219            if (option->mlpDebug)
6220              CheckCluster(headCluster, ncCols, colInfo, colOrder);
6221          } else {
6222            mdd_free(cluster);
6223            break;
6224          }
6225        }
6226
6227        ncCols = RemoveLocalVarsInCluster(mddManager, xy,
6228                                            list, nActiveRows, ncCols,
6229                                            rowInfo, colInfo,
6230                                            rowOrder, colOrder,
6231                                            moveFlag, option);
6232      }
6233    }
6234  } else { /* option->mlpCluster == 1 */
6235    if (direction == Img_Forward_c) {
6236      for (i = 0; i < nActiveRows; i++) {
6237        row = rowOrder[i];
6238        list = ALLOC(ClusterList_t, 1);
6239        memset(list, 0, sizeof(ClusterList_t));
6240
6241        if (headCluster && headCluster->flag != 3)
6242          list->flag = 1;
6243        else
6244          list->flag = 2;
6245        list->start = i;
6246        list->end = i;
6247        list->supports = ALLOC(char, nCols);
6248        memcpy(list->supports, xy[row], sizeof(char) * nCols);
6249        list->minCol = rowInfo[row].gMin;
6250        list->maxCol = rowInfo[row].gMax;
6251        list->nSupports = MlpCountSupport(list, colOrder, ncCols);
6252        list->product = bdd_dup(rowInfo[row].data.row.func);
6253        list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
6254                                                 colOrder, ncCols);
6255        if (rowInfo[row].data.row.nsVarBddArray)
6256          list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
6257        else
6258          list->nsVarBddArray = NIL(array_t);
6259
6260        if (bdd_size(list->product) >= option->clusterSize) {
6261          if (headCluster) {
6262            ncCols = RecursiveCluster(mddManager, headCluster,
6263                                        clusterSortedList,
6264                                        xy, rowInfo, colInfo,
6265                                        rowOrder, colOrder, nActiveRows, ncCols,
6266                                        direction, varPos, moveFlag, option);
6267            if (option->mlpDebug)
6268              CheckCluster(headCluster, ncCols, colInfo, colOrder);
6269          }
6270          list->flag = 3;
6271          ncCols = RemoveLocalVarsInCluster(mddManager, xy,
6272                                            list, nActiveRows, ncCols,
6273                                            rowInfo, colInfo,
6274                                            rowOrder, colOrder,
6275                                            moveFlag, option);
6276          if (option->mlpDebug)
6277            CheckCluster(headCluster, ncCols, colInfo, colOrder);
6278          list->affinity = 0.0;
6279          clusterSortedList = NIL(ClusterSortedList_t);
6280        } else if (sccBorder && i > 0 && sccBorder[i] == 1) {
6281          ncCols = RecursiveCluster(mddManager, headCluster,
6282                                        clusterSortedList,
6283                                        xy, rowInfo, colInfo,
6284                                        rowOrder, colOrder, nActiveRows, ncCols,
6285                                        direction, varPos, moveFlag, option);
6286          if (option->mlpDebug)
6287            CheckCluster(headCluster, ncCols, colInfo, colOrder);
6288          list->flag = 2;
6289          list->affinity = 0.0;
6290          clusterSortedList = NIL(ClusterSortedList_t);
6291          if (option->mlpClusterSortedList) {
6292            clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
6293                                                option->mlpClusterQuantifyVars);
6294          }
6295        } else {
6296          if (headCluster && headCluster->flag != 3) {
6297            list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
6298                                                colOrder, ncCols,
6299                                                option->mlpCluster);
6300          } else
6301            list->affinity = 0.0;
6302          if (option->mlpClusterSortedList) {
6303            clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
6304                                                option->mlpClusterQuantifyVars);
6305          }
6306        }
6307
6308        list->next = headCluster;
6309        list->prev = NIL(ClusterList_t);
6310        if (headCluster) {
6311          if (headCluster->flag == 1)
6312            headCluster->flag = 0;
6313          headCluster->prev = list;
6314        }
6315        headCluster = list;
6316      }
6317    } else {
6318      for (i = nActiveRows - 1; i >= 0; i--) {
6319        row = rowOrder[i];
6320        list = ALLOC(ClusterList_t, 1);
6321        memset(list, 0, sizeof(ClusterList_t));
6322
6323        if (headCluster && headCluster->flag != 3)
6324          list->flag = 1;
6325        else
6326          list->flag = 2;
6327        list->start = i;
6328        list->end = i;
6329        list->supports = ALLOC(char, nCols);
6330        memcpy(list->supports, xy[row], sizeof(char) * nCols);
6331        list->minCol = rowInfo[row].gMin;
6332        list->maxCol = rowInfo[row].gMax;
6333        list->nSupports = MlpCountSupport(list, colOrder, ncCols);
6334        list->product = bdd_dup(rowInfo[row].data.row.func);
6335        list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
6336                                                 colOrder, ncCols);
6337        if (rowInfo[row].data.row.nsVarBddArray)
6338          list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
6339        else
6340          list->nsVarBddArray = NIL(array_t);
6341
6342        if ( bdd_size(list->product) >= option->clusterSize) {
6343          if (headCluster) {
6344            ncCols = RecursiveCluster(mddManager, headCluster,
6345                                        clusterSortedList,
6346                                        xy, rowInfo, colInfo,
6347                                        rowOrder, colOrder, nActiveRows, ncCols,
6348                                        direction, varPos, moveFlag, option);
6349            if (option->mlpDebug)
6350              CheckCluster(headCluster, ncCols, colInfo, colOrder);
6351          }
6352          list->flag = 3;
6353          ncCols = RemoveLocalVarsInCluster(mddManager, xy,
6354                                            list, nActiveRows, ncCols,
6355                                            rowInfo, colInfo,
6356                                            rowOrder, colOrder,
6357                                            moveFlag, option);
6358          if (option->mlpDebug)
6359            CheckCluster(headCluster, ncCols, colInfo, colOrder);
6360          list->affinity = 0.0;
6361          clusterSortedList = NIL(ClusterSortedList_t);
6362        } else if (sccBorder && i < (nActiveRows - 1) && sccBorder[i] == 2) {
6363          ncCols = RecursiveCluster(mddManager, headCluster,
6364                                        clusterSortedList,
6365                                        xy, rowInfo, colInfo,
6366                                        rowOrder, colOrder, nActiveRows, ncCols,
6367                                        direction, varPos, moveFlag, option);
6368          if (option->mlpDebug)
6369            CheckCluster(headCluster, ncCols, colInfo, colOrder);
6370          list->flag = 2;
6371          list->affinity = 0.0;
6372          clusterSortedList = NIL(ClusterSortedList_t);
6373          if (option->mlpClusterSortedList) {
6374            clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
6375                                                option->mlpClusterQuantifyVars);
6376          }
6377        } else {
6378          if (headCluster && headCluster->flag != 3) {
6379            list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
6380                                                colOrder, ncCols,
6381                                                option->mlpCluster);
6382          } else
6383            list->affinity = 0.0;
6384          if (option->mlpClusterSortedList) {
6385            clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
6386                                                option->mlpClusterQuantifyVars);
6387          }
6388        }
6389
6390        list->next = headCluster;
6391        list->prev = NIL(ClusterList_t);
6392        if (headCluster) {
6393          if (headCluster->flag == 1)
6394            headCluster->flag = 0;
6395          headCluster->prev = list;
6396        }
6397        headCluster = list;
6398
6399        if (option->mlpClusterSortedList && option->mlpDebug) {
6400          int   n1, n2;
6401
6402          n1 = CountClusterList(headCluster);
6403          n2 = CountClusterSortedList(clusterSortedList);
6404          assert(n1 == n2);
6405        }
6406      }
6407    }
6408
6409    if (headCluster->flag == 1) {
6410      ncCols = RecursiveCluster(mddManager, headCluster, clusterSortedList,
6411                                xy, rowInfo, colInfo,
6412                                rowOrder, colOrder, nActiveRows, ncCols,
6413                                direction, varPos, moveFlag, option);
6414      if (option->mlpDebug)
6415        CheckCluster(headCluster, ncCols, colInfo, colOrder);
6416    }
6417  }
6418
6419  list = headCluster;
6420  one = bdd_one(mddManager);
6421  while (list) {
6422    if (bdd_equal(list->product, one)) {
6423      assert(list->nSupports == 0);
6424
6425      prevList = list->prev;
6426      nextList = list->next;
6427      if ((!prevList) && (!nextList)) /* unity relation */
6428        break;
6429
6430      mdd_free(list->product);
6431      if (list->nsVarBddArray)
6432        array_free(list->nsVarBddArray);
6433      FREE(list->supports);
6434
6435      if (nextList) {
6436        if (list->start < nextList->start)
6437          nextList->start = list->start;
6438        if (list->end > nextList->end)
6439          nextList->end = list->end;
6440
6441        if (list == headCluster)
6442          headCluster = nextList;
6443
6444        FREE(list);
6445      } else {
6446        if (list->start < prevList->start)
6447          prevList->start = list->start;
6448        if (list->end > prevList->end)
6449          prevList->end = list->end;
6450        FREE(list);
6451      }
6452      if (prevList)
6453        prevList->next = nextList;
6454      if (nextList)
6455        nextList->prev = prevList;
6456      list = nextList;
6457      continue;
6458    }
6459    list = list->next;
6460  }
6461  bdd_free(one);
6462
6463  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
6464    PrintMatrixWithCluster(xy, headCluster, ncCols, rowOrder, colOrder,
6465                           direction);
6466    fprintf(vis_stdout, "******** cluster matrix ************\n");
6467    PrintClusterMatrix(headCluster, ncCols, colOrder, direction);
6468  }
6469  if (option->mlpDebug)
6470    CheckCluster(headCluster, ncCols, colInfo, colOrder);
6471
6472  ncRows = 0;
6473  nonAppearingVarBddArray = NIL(array_t);
6474  if ((direction == Img_Forward_c && option->mlpReorder) ||
6475      (direction == Img_Backward_c && option->mlpPreReorder) ||
6476      option->mlpPostProcess >= 2) {
6477    list = headCluster;
6478    while (list) {
6479      row = rowOrder[ncRows];
6480
6481      mdd_free(rowInfo[row].data.row.func);
6482      rowInfo[row].data.row.func = list->product;
6483      list->product = NIL(mdd_t);
6484
6485      if (xy[row])
6486        FREE(xy[row]);
6487      xy[row] = list->supports;
6488      list->supports = NIL(char);
6489
6490      rowInfo[row].gNum = list->nSupports;
6491      rowInfo[row].gMin = list->minCol;
6492      rowInfo[row].gMax = list->maxCol;
6493      rowInfo[row].lNum = list->nSupports;
6494      rowInfo[row].lMin = list->minCol;
6495      rowInfo[row].lMax = list->maxCol;
6496      rowInfo[row].prevG = -1;
6497      rowInfo[row].nextG = ncCols;
6498
6499      if (list->nsVarBddArray) {
6500        if (rowInfo[row].data.row.nsVarBddArray)
6501          array_free(rowInfo[row].data.row.nsVarBddArray);
6502        rowInfo[row].data.row.nsVarBddArray = list->nsVarBddArray;
6503        list->nsVarBddArray = NIL(array_t);
6504      }
6505
6506      nextList = list->next;
6507      FREE(list);
6508      ncRows++;
6509      list = nextList;
6510    }
6511
6512    if (direction == Img_Forward_c) {
6513      for (i = 0; i < ncRows; i++) {
6514        cRowOrder[i] = rowOrder[ncRows - i - 1];
6515        rowInfo[rowOrder[ncRows - i - 1]].pos = i;
6516      }
6517    } else {
6518      for (i = 0; i < ncRows; i++) {
6519        cRowOrder[i] = rowOrder[i];
6520        rowInfo[rowOrder[i]].pos = i;
6521      }
6522    }
6523
6524    for (j = 0; j < ncCols; j++) {
6525      col = colOrder[j];
6526      colInfo[col].gNum = 0;
6527      colInfo[col].gMin = ncRows;
6528      colInfo[col].gMax = -1;
6529      for (i = 0; i < ncRows; i++) {
6530        row = cRowOrder[i];
6531        if (xy[row][col]) {
6532          colInfo[col].gNum++;
6533          if (colInfo[col].gMin == ncRows)
6534            colInfo[col].gMin = row;
6535          colInfo[col].gMax = row;
6536        }
6537      }
6538      colInfo[col].lNum = colInfo[col].gNum;
6539      colInfo[col].lMin = colInfo[col].gMin;
6540      colInfo[col].lMax = colInfo[col].gMax;
6541      colInfo[col].prevG = -1;
6542      colInfo[col].nextG = ncRows;
6543    }
6544  } else {
6545    if (direction == Img_Forward_c) {
6546      if (arraySmoothVarBddArray) {
6547        nonAppearingVarBddArray = array_fetch(array_t *,
6548                                              arraySmoothVarBddArray, 0);
6549        if (nCols > ncCols) {
6550          existFlag = ALLOC(char, nVars);
6551          memset(existFlag, 0, sizeof(char) * nVars);
6552
6553          for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
6554            nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
6555            index = (int)bdd_top_var_id(nsVar);
6556            existFlag[index] = 1;
6557          }
6558
6559          for (i = ncCols; i < nCols; i++) {
6560            col = colOrder[i];
6561            index = (int)bdd_top_var_id(colInfo[col].data.col.var);
6562            if (!existFlag[index]) {
6563              array_insert_last(bdd_t *, nonAppearingVarBddArray,
6564                                bdd_dup(colInfo[col].data.col.var));
6565            }
6566          }
6567
6568          FREE(existFlag);
6569        }
6570        qVarPos = ncCols - 1;
6571        if (qVarPos >= 0) {
6572          col = colOrder[qVarPos];
6573          while (colInfo[col].gNum == 0) {
6574            array_insert_last(bdd_t *, nonAppearingVarBddArray,
6575                                bdd_dup(colInfo[col].data.col.var));
6576            if (qVarPos == 0)
6577              break;
6578            qVarPos--;
6579            col = colOrder[qVarPos];
6580          }
6581        }
6582      } else
6583        qVarPos = 0; /* to avoid warning */
6584    } else {
6585      if (arraySmoothVarBddArray) {
6586        nonAppearingVarBddArray = array_fetch(array_t *,
6587                                                arraySmoothVarBddArray, 0);
6588        if (nCols > ncCols) {
6589          for (i = ncCols; i < nCols; i++) {
6590            col = colOrder[i];
6591            if (colInfo[col].data.col.type == 2) {
6592              array_insert_last(bdd_t *, nonAppearingVarBddArray,
6593                                bdd_dup(colInfo[col].data.col.var));
6594            }
6595          }
6596        }
6597        qVarPos = ncCols - 1;
6598        if (qVarPos >= 0) {
6599          col = colOrder[qVarPos];
6600          while (colInfo[col].gNum == 0) {
6601            if (colInfo[col].data.col.type == 2) {
6602              array_insert_last(bdd_t *, nonAppearingVarBddArray,
6603                                bdd_dup(colInfo[col].data.col.var));
6604            }
6605            if (qVarPos == 0)
6606              break;
6607            qVarPos--;
6608            col = colOrder[qVarPos];
6609          }
6610        }
6611
6612        existFlag = ALLOC(char, nVars);
6613        memset(existFlag, 0, sizeof(char) * nVars);
6614
6615        for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
6616          nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
6617          index = (int)bdd_top_var_id(nsVar);
6618          existFlag[index] = 1;
6619        }
6620
6621        if (nRows > nActiveRows) {
6622          for (i = nActiveRows; i < nRows; i++) {
6623            row = rowOrder[i];
6624            tmpArray = rowInfo[row].data.row.nsVarBddArray;
6625            for (j = 0; j < array_n(tmpArray); j++) {
6626              nsVar = array_fetch(bdd_t *, tmpArray, j);
6627              index = (int)bdd_top_var_id(nsVar);
6628              existFlag[index] = 1;
6629            }
6630          }
6631        }
6632
6633        list = headCluster;
6634        while (list) {
6635          supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
6636          for (i = 0; i < array_n(supportArray); i++) {
6637            index = array_fetch(int, supportArray, i);
6638            existFlag[index] = 1;
6639          }
6640          array_free(supportArray);
6641          list = list->next;
6642        }
6643
6644        list = headCluster;
6645        while (list) {
6646          for (i = 0; i < array_n(list->nsVarBddArray); i++) {
6647            nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
6648            index = (int)bdd_top_var_id(nsVar);
6649            if (!existFlag[index]) {
6650              tmpArray = array_alloc(mdd_t *, 0);
6651              for (j = 0; j < i; j++) {
6652                nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
6653                array_insert_last(mdd_t *, tmpArray, nsVar);
6654              }
6655              for (j = i + 1; j < array_n(list->nsVarBddArray); j++) {
6656                nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
6657                index = (int)bdd_top_var_id(nsVar);
6658                if (existFlag[index])
6659                  array_insert_last(mdd_t *, tmpArray, nsVar);
6660              }
6661              array_free(list->nsVarBddArray);
6662              list->nsVarBddArray = tmpArray;
6663              break;
6664            }
6665          }
6666          list = list->next;
6667        }
6668
6669        for (i = 0; i < array_n(nsVarBddArray); i++) {
6670          nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
6671          index = (int)bdd_top_var_id(nsVar);
6672          if (!existFlag[index])
6673            array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
6674        }
6675
6676        FREE(existFlag);
6677      } else
6678        qVarPos = 0; /* to avoid warning */
6679    }
6680
6681    if (direction == Img_Backward_c && nRows > nActiveRows) {
6682      cluster = bdd_one(mddManager);
6683      if (arraySmoothVarBddArray)
6684        smoothVarBddArray = array_alloc(array_t *, 0);
6685      else
6686        smoothVarBddArray = NIL(array_t);
6687      for (i = nActiveRows; i < nRows; i++) {
6688        row = rowOrder[i];
6689        relation = rowInfo[row].data.row.func;
6690        if (bdd_is_tautology(relation, 1))
6691          continue;
6692        if (smoothVarBddArray) {
6693          tmpArray = rowInfo[row].data.row.nsVarBddArray;
6694          for (j = 0; j < array_n(tmpArray); j++) {
6695            nsVar = array_fetch(bdd_t *, tmpArray, j);
6696            array_insert_last(mdd_t *, smoothVarBddArray, bdd_dup(nsVar));
6697          }
6698        }
6699        tempCluster = bdd_and(cluster, relation, 1, 1);
6700        bdd_free(cluster);
6701        cluster = tempCluster;
6702      }
6703      if (bdd_is_tautology(cluster, 1)) {
6704        mdd_free(cluster);
6705        if (smoothVarBddArray)
6706          mdd_array_free(smoothVarBddArray);
6707      } else {
6708        array_insert_last(bdd_t *, clusterArray, cluster);
6709        if (arraySmoothVarBddArray) {
6710          array_insert_last(array_t *, arraySmoothVarBddArray,
6711                            smoothVarBddArray);
6712        }
6713        ncRows++;
6714      }
6715    }
6716
6717    list = headCluster;
6718    while (list) {
6719      array_insert_last(mdd_t *, clusterArray, list->product);
6720      list->product = NIL(mdd_t);
6721
6722      if (arraySmoothVarBddArray) {
6723        if (direction == Img_Forward_c) {
6724          smoothVarBddArray = array_alloc(array_t *, 0);
6725          if (qVarPos >= 0) {
6726            col = colOrder[qVarPos];
6727            while (rowInfo[colInfo[col].gMin].pos >= list->start &&
6728                   rowInfo[colInfo[col].gMin].pos <= list->end) {
6729              array_insert_last(bdd_t *, smoothVarBddArray,
6730                                bdd_dup(colInfo[col].data.col.var));
6731              if (qVarPos == 0)
6732                break;
6733              qVarPos--;
6734              col = colOrder[qVarPos];
6735            }
6736          }
6737          array_insert_last(array_t *, arraySmoothVarBddArray,
6738                            smoothVarBddArray);
6739        } else {
6740          smoothVarBddArray = array_alloc(array_t *, 0);
6741          for (i = 0; i < array_n(list->nsVarBddArray); i++) {
6742            nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
6743            array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
6744          }
6745
6746          if (list->nSupports > 0) {
6747            s1 = colInfo[list->minCol].pos;
6748            t1 = colInfo[list->maxCol].pos;
6749            for (i = s1; i <= t1; i++) {
6750              col = colOrder[i];
6751              if (colInfo[col].data.col.type == 2) {
6752                if (rowInfo[colInfo[col].gMax].pos >= list->start &&
6753                    rowInfo[colInfo[col].gMax].pos <= list->end) {
6754                  array_insert_last(bdd_t *, smoothVarBddArray,
6755                                    bdd_dup(colInfo[col].data.col.var));
6756                }
6757              }
6758            }
6759          }
6760          array_insert_last(array_t *, arraySmoothVarBddArray,
6761                            smoothVarBddArray);
6762        }
6763      }
6764
6765      nextList = list->next;
6766      if (list->nsVarBddArray)
6767        array_free(list->nsVarBddArray);
6768      FREE(list->supports);
6769      FREE(list);
6770      ncRows++;
6771      list = nextList;
6772    }
6773
6774    if (direction == Img_Forward_c && nRows > nActiveRows) {
6775      cluster = bdd_one(mddManager);
6776      for (i = nActiveRows; i < nRows; i++) {
6777        row = rowOrder[i];
6778        relation = rowInfo[row].data.row.func;
6779        if (bdd_is_tautology(relation, 1))
6780          continue;
6781        tempCluster = bdd_and(cluster, relation, 1, 1);
6782        bdd_free(cluster);
6783        cluster = tempCluster;
6784      }
6785      if (bdd_is_tautology(cluster, 1))
6786        mdd_free(cluster);
6787      else {
6788        array_insert_last(bdd_t *, clusterArray, cluster);
6789        if (arraySmoothVarBddArray) {
6790          smoothVarBddArray = array_alloc(array_t *, 0);
6791          array_insert_last(array_t *, arraySmoothVarBddArray,
6792                            smoothVarBddArray);
6793        }
6794        ncRows++;
6795      }
6796    }
6797  }
6798
6799  *nClusterRows = ncRows;
6800  *nClusterCols = ncCols;
6801
6802  if (option->mlpVerbosity) {
6803    finalTime = util_cpu_time();
6804    fprintf(vis_stdout, "time for clustering = %10g\n",
6805           (double)(finalTime - initialTime) / 1000.0);
6806  }
6807}
6808
6809
6810/**Function********************************************************************
6811
6812  Synopsis    [Counts the number of supports of the list.]
6813
6814  Description [Counts the number of supports of the list.]
6815
6816  SideEffects []
6817
6818******************************************************************************/
6819static int
6820MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols)
6821{
6822  int   i, col;
6823  int   nSupports = 0;
6824
6825  for (i = 0; i < nActiveCols; i++) {
6826    col = colOrder[i];
6827    if (list->supports[col])
6828      nSupports++;
6829  }
6830  return(nSupports);
6831}
6832
6833
6834/**Function********************************************************************
6835
6836  Synopsis    [Computes the affinity of two lists.]
6837
6838  Description [Computes the affinity of two lists.]
6839
6840  SideEffects []
6841
6842******************************************************************************/
6843static float
6844MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList,
6845                RcInfo_t *colInfo, int *colOrder,
6846                int nActiveCols, int clusterMethod)
6847{
6848  ClusterList_t *minList, *maxList;
6849  int           i, col, s, t;
6850  int           nOverlaps = 0;
6851  float         affinity;
6852
6853  if (curList->nSupports <= nextList->nSupports) {
6854    minList = curList;
6855    maxList = nextList;
6856  } else {
6857    minList = nextList;
6858    maxList = curList;
6859  }
6860
6861  s = colInfo[minList->minCol].pos;
6862  t = colInfo[minList->maxCol].pos;
6863  for (i = s; i <= t; i++) {
6864    col = colOrder[i];
6865    if (minList->supports[col] && maxList->supports[col])
6866      nOverlaps++;
6867  }
6868
6869  if (clusterMethod == 1)
6870    affinity = (float)nOverlaps / (float)minList->nSupports;
6871  else {
6872    affinity = (float)nOverlaps /
6873                (float)(minList->nSupports + maxList->nSupports - nOverlaps);
6874  }
6875  return(affinity);
6876}
6877
6878
6879/**Function********************************************************************
6880
6881  Synopsis    [Clusters recursively with affinity.]
6882
6883  Description [Clusters recursively with affinity.]
6884
6885  SideEffects []
6886
6887******************************************************************************/
6888static int
6889RecursiveCluster(mdd_manager *mddManager, ClusterList_t *headCluster,
6890                 ClusterSortedList_t *clusterSortedList,
6891                 char **xy, RcInfo_t *rowInfo, RcInfo_t *colInfo,
6892                 int *rowOrder, int *colOrder,
6893                 int nActiveRows, int nClusterCols,
6894                 Img_DirectionType direction, int *varPos,
6895                 int moveFlag, ImgTrmOption_t *option)
6896{
6897  ClusterSortedList_t   *sortedList, *nextSortedList, *prevSortedList;
6898  ClusterSortedList_t   *firstSortedList, *secondSortedList, *saveSortedList;
6899  ClusterSortedList_t   *tailSortedList1, *tailSortedList2;
6900  ClusterList_t         *list, *best;
6901  int                   i, n1, n2;
6902  int                   s1, t1, s2;
6903  mdd_t                 *product;
6904  int                   merge, index;
6905  array_t               *supportArray;
6906
6907  if (headCluster->flag == 3)
6908    return(nClusterCols);
6909
6910  assert(headCluster);
6911  if (option->mlpClusterSortedList && option->mlpDebug) {
6912    n1 = CountClusterList(headCluster);
6913    n2 = CountClusterSortedList(clusterSortedList);
6914    assert(n1 == n2);
6915  }
6916
6917  if (headCluster->flag == 2) {
6918    assert(!headCluster->next || headCluster->next->flag == 3);
6919    headCluster->flag = 3;
6920    nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, headCluster,
6921                                            nActiveRows, nClusterCols,
6922                                            rowInfo, colInfo,
6923                                            rowOrder, colOrder,
6924                                            moveFlag, option);
6925    if (clusterSortedList) {
6926      assert(!clusterSortedList->next);
6927      FREE(clusterSortedList);
6928    }
6929    return(nClusterCols);
6930  }
6931
6932  merge = 0;
6933  best = NIL(ClusterList_t);
6934  if (option->mlpClusterMerge) {
6935    /* NEED */
6936  }
6937
6938  if (!best) {
6939    if (clusterSortedList)
6940      best = clusterSortedList->list;
6941    else {
6942      best = headCluster;
6943      list = headCluster->next;
6944      while (list) {
6945        if (list->flag == 2)
6946          break;
6947        if (option->mlpClusterQuantifyVars) {
6948          if (list->nQuantifyVars < best->nQuantifyVars ||
6949              (list->nQuantifyVars == best->nQuantifyVars &&
6950               list->affinity > best->affinity)) {
6951            best = list;
6952          }
6953        } else {
6954          if (list->affinity < option->mlpAffinityThreshold) {
6955            list = list->next;
6956            continue;
6957          }
6958          if (list->affinity > best->affinity ||
6959              (list->affinity == best->affinity &&
6960               list->nQuantifyVars < best->nQuantifyVars)) {
6961            best = list;
6962          }
6963        }
6964        list = list->next;
6965      }
6966    }
6967  }
6968  assert(best->next && best->next->flag != 3);
6969
6970  list = best->next;
6971  product = mdd_and(best->product, list->product, 1, 1);
6972
6973  if (merge == 0 && bdd_size(product) > option->clusterSize) {
6974    mdd_free(product);
6975
6976    firstSortedList = NIL(ClusterSortedList_t);
6977    secondSortedList = NIL(ClusterSortedList_t);
6978    if (option->mlpClusterSortedList) {
6979      tailSortedList1 = NIL(ClusterSortedList_t);
6980      tailSortedList2 = NIL(ClusterSortedList_t);
6981      sortedList = clusterSortedList;
6982      while (sortedList) {
6983        nextSortedList = sortedList->next;
6984        if ((best->start > list->start &&
6985             sortedList->list->start >= best->start) ||
6986            (best->start < list->start &&
6987             sortedList->list->start <= best->start)) {
6988          if (tailSortedList1)
6989            tailSortedList1->next = sortedList;
6990          else
6991            firstSortedList = sortedList;
6992          tailSortedList1 = sortedList;
6993        } else {
6994          if (tailSortedList2)
6995            tailSortedList2->next = sortedList;
6996          else
6997            secondSortedList = sortedList;
6998          tailSortedList2 = sortedList;
6999        }
7000        sortedList->next = NIL(ClusterSortedList_t);
7001        sortedList = nextSortedList;
7002      }
7003    }
7004
7005    if (best == headCluster) {
7006      best->flag = 3;
7007      if (option->mlpClusterSortedList) {
7008        sortedList = firstSortedList;
7009        firstSortedList = firstSortedList->next;
7010        FREE(sortedList);
7011        assert(!firstSortedList);
7012      }
7013      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
7014                                                nActiveRows, nClusterCols,
7015                                                rowInfo, colInfo,
7016                                                rowOrder, colOrder,
7017                                                moveFlag, option);
7018    } else {
7019      best->flag = 2;
7020      if (option->mlpClusterSortedList) {
7021        sortedList = firstSortedList;
7022        prevSortedList = NIL(ClusterSortedList_t);
7023        saveSortedList = NIL(ClusterSortedList_t);
7024        while (sortedList) {
7025          nextSortedList = sortedList->next;
7026          if (sortedList->list == best) {
7027            if (nextSortedList) {
7028              if (prevSortedList)
7029                prevSortedList->next = sortedList->next;
7030              else
7031                firstSortedList = sortedList->next;
7032            }
7033            saveSortedList = sortedList;
7034            sortedList->next = NIL(ClusterSortedList_t);
7035            sortedList = nextSortedList;
7036            continue;
7037          }
7038          prevSortedList = sortedList;
7039          sortedList = nextSortedList;
7040        }
7041        prevSortedList->next = saveSortedList;
7042      }
7043      nClusterCols = RecursiveCluster(mddManager, headCluster, firstSortedList,
7044                                        xy, rowInfo, colInfo,
7045                                        rowOrder, colOrder,
7046                                        nActiveRows, nClusterCols,
7047                                        direction, varPos, moveFlag, option);
7048    }
7049    if (option->mlpDebug) {
7050      CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
7051      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
7052                    rowInfo, colInfo, rowOrder, colOrder,
7053                    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
7054    }
7055
7056    if (list->flag == 0) {
7057      list->flag = 1;
7058      nClusterCols = RecursiveCluster(mddManager, list, secondSortedList,
7059                                        xy, rowInfo, colInfo,
7060                                        rowOrder, colOrder,
7061                                        nActiveRows, nClusterCols,
7062                                        direction, varPos, moveFlag, option);
7063    } else {
7064      list->flag = 3;
7065      sortedList = secondSortedList;
7066      secondSortedList = secondSortedList->next;
7067      FREE(sortedList);
7068      assert(!secondSortedList);
7069      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, list,
7070                                                nActiveRows, nClusterCols,
7071                                                rowInfo, colInfo,
7072                                                rowOrder, colOrder,
7073                                                moveFlag, option);
7074    }
7075    if (option->mlpDebug) {
7076      CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
7077      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
7078                    rowInfo, colInfo, rowOrder, colOrder,
7079                    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
7080    }
7081  } else {
7082    if (merge == 0 && option->mlpClusterSortedList) {
7083      sortedList = clusterSortedList->next;
7084      FREE(clusterSortedList);
7085      clusterSortedList = sortedList;
7086    }
7087
7088    mdd_free(best->product);
7089    best->product = product;
7090
7091    if (list->flag == 2) {
7092      if (best->flag == 1)
7093        best->flag = 3;
7094      else
7095        best->flag = 2;
7096    }
7097
7098    best->nSupports = 0;
7099    best->minCol = nClusterCols;
7100    best->maxCol = -1;
7101    s1 = nClusterCols;
7102    t1 = -1;
7103    supportArray = mdd_get_bdd_support_ids(mddManager, best->product);
7104    for (i = 0; i < array_n(supportArray); i++) {
7105      index = array_fetch(int, supportArray, i);
7106      if (varPos[index] == 0) {
7107        if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
7108          continue;
7109      }
7110      index = varPos[index];
7111      best->supports[index] = 1;
7112      best->nSupports++;
7113      s2 = colInfo[index].pos;
7114      if (s2 < s1) {
7115        s1 = s2;
7116        best->minCol = index;
7117      }
7118      if (s2 > t1) {
7119        t1 = s2;
7120        best->maxCol = index;
7121      }
7122    }
7123    array_free(supportArray);
7124
7125    if (best->nsVarBddArray)
7126      array_append(best->nsVarBddArray, list->nsVarBddArray);
7127
7128    if (list->start < best->start)
7129      best->start = list->start;
7130    if (list->end > best->end)
7131      best->end = list->end;
7132
7133    if (option->mlpClusterSortedList) {
7134      sortedList = clusterSortedList;
7135      prevSortedList = NIL(ClusterSortedList_t);
7136      if (merge == 0) {
7137        while (sortedList) {
7138          nextSortedList = sortedList->next;
7139          if (option->mlpClusterDynamic) {
7140            if (sortedList->list == list || sortedList->list == best->prev) {
7141              if (prevSortedList)
7142                prevSortedList->next = sortedList->next;
7143              else
7144                clusterSortedList = sortedList->next;
7145              FREE(sortedList);
7146              sortedList = nextSortedList;
7147              continue;
7148            }
7149          } else {
7150            if (sortedList->list == list) {
7151              best->affinity = list->affinity;
7152              sortedList->list = best;
7153              break;
7154            }
7155          }
7156          prevSortedList = sortedList;
7157          sortedList = nextSortedList;
7158        }
7159      } else {
7160        while (sortedList) {
7161          nextSortedList = sortedList->next;
7162          if (option->mlpClusterDynamic) {
7163            if (sortedList->list == best ||
7164                sortedList->list == list || sortedList->list == best->prev) {
7165              if (prevSortedList)
7166                prevSortedList->next = sortedList->next;
7167              else
7168                clusterSortedList = sortedList->next;
7169              FREE(sortedList);
7170              sortedList = nextSortedList;
7171              continue;
7172            }
7173          } else {
7174            if (sortedList->list == best) {
7175              if (prevSortedList)
7176                prevSortedList->next = sortedList->next;
7177              else
7178                clusterSortedList = sortedList->next;
7179              FREE(sortedList);
7180              sortedList = nextSortedList;
7181              continue;
7182            } else if (sortedList->list == list) {
7183              best->affinity = list->affinity;
7184              sortedList->list = best;
7185              break;
7186            }
7187          }
7188          prevSortedList = sortedList;
7189          sortedList = nextSortedList;
7190        }
7191      }
7192    }
7193
7194    best->next = list->next;
7195    if (list->next)
7196      list->next->prev = best;
7197
7198    mdd_free(list->product);
7199    if (list->nsVarBddArray)
7200      array_free(list->nsVarBddArray);
7201    FREE(list->supports);
7202    FREE(list);
7203
7204    if (merge && best->flag != 3) {
7205      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
7206                                                nActiveRows, nClusterCols,
7207                                                rowInfo, colInfo,
7208                                                rowOrder, colOrder,
7209                                                moveFlag, option);
7210    }
7211
7212    if (best->flag == 3) {
7213      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
7214                                                nActiveRows, nClusterCols,
7215                                                rowInfo, colInfo,
7216                                                rowOrder, colOrder,
7217                                                moveFlag, option);
7218    } else {
7219      if (option->mlpClusterDynamic) {
7220        if (best->flag == 2)
7221          best->affinity = 0.0;
7222        else {
7223          best->affinity = MlpSupportAffinity(best, best->next, colInfo,
7224                                                colOrder, nClusterCols,
7225                                                option->mlpCluster);
7226        }
7227        if (best != headCluster) {
7228          best->prev->affinity = MlpSupportAffinity(best->prev, best, colInfo,
7229                                                    colOrder, nClusterCols,
7230                                                    option->mlpCluster);
7231        }
7232      }
7233      if (option->mlpClusterQuantifyVars == 2) {
7234        best->nQuantifyVars = MlpNumQuantifyVars(best, rowInfo, colInfo,
7235                                                 colOrder, nClusterCols);
7236      }
7237      if (option->mlpClusterSortedList && option->mlpClusterDynamic) {
7238        clusterSortedList = ClusterSortedListInsert(clusterSortedList, best,
7239                                                option->mlpClusterQuantifyVars);
7240        if (best != headCluster) {
7241          clusterSortedList = ClusterSortedListInsert(clusterSortedList,
7242                                                best->prev,
7243                                                option->mlpClusterQuantifyVars);
7244        }
7245      }
7246    }
7247
7248    if (headCluster->flag == 1) {
7249      if (option->mlpDebug) {
7250        CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
7251        CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
7252                    rowInfo, colInfo, rowOrder, colOrder,
7253                    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
7254      }
7255      nClusterCols = RecursiveCluster(mddManager, headCluster,
7256                                        clusterSortedList,
7257                                        xy, rowInfo, colInfo,
7258                                        rowOrder, colOrder,
7259                                        nActiveRows, nClusterCols,
7260                                        direction, varPos, moveFlag, option);
7261    } else {
7262      if (!option->mlpClusterDynamic) {
7263        assert(!clusterSortedList->next);
7264        FREE(clusterSortedList);
7265      }
7266    }
7267  }
7268
7269  return(nClusterCols);
7270}
7271
7272
7273/**Function********************************************************************
7274
7275  Synopsis    [Removes local variables in a cluster.]
7276
7277  Description [Removes local variables in a cluster.]
7278
7279  SideEffects []
7280
7281******************************************************************************/
7282static int
7283RemoveLocalVarsInCluster(mdd_manager *mddManager, char **xy,
7284                         ClusterList_t *list,
7285                         int nActiveRows, int nClusterCols,
7286                         RcInfo_t *rowInfo, RcInfo_t *colInfo,
7287                         int *rowOrder, int *colOrder,
7288                         int moveFlag, ImgTrmOption_t *option)
7289{
7290  int           i, j, k, row, col, otherCol;
7291  int           s1, t1, s2, t2, s3, t3;
7292  mdd_t         *product;
7293  array_t       *localVarBddArray = NIL(array_t);
7294
7295  s1 = colInfo[list->minCol].pos;
7296  t1 = colInfo[list->maxCol].pos;
7297  for (i = t1; i >= s1; i--) {
7298    col = colOrder[i];
7299    if (colInfo[col].data.col.type == 2 &&
7300        rowInfo[colInfo[col].gMin].pos >= list->start &&
7301        rowInfo[colInfo[col].gMax].pos <= list->end) {
7302      if (!localVarBddArray)
7303        localVarBddArray = array_alloc(bdd_t *, 0);
7304      array_insert_last(bdd_t *, localVarBddArray, colInfo[col].data.col.var);
7305
7306      list->nSupports--;
7307      if (list->nSupports == 0) {
7308        list->minCol = -1;
7309        list->maxCol = -1;
7310      } else if (list->nSupports == 1) {
7311        if (list->minCol == col)
7312          list->minCol = list->maxCol;
7313        else
7314          list->maxCol = list->minCol;
7315      } else if (list->nSupports > 1) {
7316        if (list->minCol == col) {
7317          for (j = i + 1; j <= t1; j++) {
7318            otherCol = colOrder[j];
7319            if (list->supports[otherCol]) {
7320              list->minCol = otherCol;
7321              break;
7322            }
7323          }
7324        } else if (list->maxCol == col) {
7325          for (j = i - 1; j >= s1; j--) {
7326            otherCol = colOrder[j];
7327            if (list->supports[otherCol]) {
7328              list->maxCol = otherCol;
7329              break;
7330            }
7331          }
7332        }
7333      }
7334
7335      s2 = list->start;
7336      t2 = list->end;
7337      for (j = s2; j <= t2; j++) {
7338        row = rowOrder[j];
7339        if (xy[row][col]) {
7340          rowInfo[row].gNum--;
7341          if (rowInfo[row].gNum > 0) {
7342            s3 = colInfo[rowInfo[row].gMin].pos;
7343            t3 = colInfo[rowInfo[row].gMax].pos;
7344            if (rowInfo[row].gMin == col) {
7345              for (k = i + 1; k <= t3; k++) {
7346                otherCol = colOrder[k];
7347                if (xy[row][otherCol]) {
7348                  rowInfo[row].gMin = otherCol;
7349                  break;
7350                }
7351              }
7352            } else if (rowInfo[row].gMax == col) {
7353              for (k = i - 1; k >= s3; k--) {
7354                otherCol = colOrder[k];
7355                if (xy[row][otherCol]) {
7356                  rowInfo[row].gMax = otherCol;
7357                  break;
7358                }
7359              }
7360            }
7361          }
7362        }
7363      }
7364
7365      for (j = i; j < nClusterCols - 1; j++) {
7366        colOrder[j] = colOrder[j + 1];
7367        colInfo[colOrder[j]].pos = j;
7368      }
7369      colOrder[nClusterCols - 1] = col;
7370      colInfo[col].pos = nClusterCols - 1;
7371
7372      nClusterCols--;
7373
7374      if (option->mlpDebug) {
7375        CheckCluster(list, nClusterCols, colInfo, colOrder);
7376        CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
7377                    rowInfo, colInfo, rowOrder, colOrder,
7378                    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
7379      }
7380    }
7381  }
7382
7383  if (localVarBddArray) {
7384    product = bdd_smooth(list->product, localVarBddArray);
7385    mdd_free(list->product);
7386    list->product = product;
7387    array_free(localVarBddArray);
7388    UpdateDisapearingPsVarsInCluster(mddManager, xy,
7389                        nActiveRows, nClusterCols,
7390                        rowOrder, colOrder, rowInfo, colInfo,
7391                        list, moveFlag, option);
7392  }
7393
7394  return(nClusterCols);
7395}
7396
7397
7398/**Function********************************************************************
7399
7400  Synopsis    [Retuns the number of variables to be quantified in a list.]
7401
7402  Description [Retuns the number of variables to be quantified in a list.]
7403
7404  SideEffects []
7405
7406******************************************************************************/
7407static int
7408MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo,
7409                   int *colOrder, int nClusterCols)
7410{
7411  int   i, s, t, col;
7412  int   nQuantifyVars = 0;
7413
7414  s = colInfo[list->minCol].pos;
7415  t = colInfo[list->maxCol].pos;
7416  for (i = t; i >= s; i--) {
7417    col = colOrder[i];
7418    if (rowInfo[colInfo[col].gMin].pos >= list->start &&
7419        rowInfo[colInfo[col].gMin].pos <= list->end) {
7420      nQuantifyVars++;
7421    } else
7422      break;
7423  }
7424
7425  return(nQuantifyVars);
7426}
7427
7428
7429/**Function********************************************************************
7430
7431  Synopsis    [Inserts a cluster in a sorting list.]
7432
7433  Description [Inserts a cluster in a sorting list.]
7434
7435  SideEffects []
7436
7437******************************************************************************/
7438static ClusterSortedList_t *
7439ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList,
7440                        ClusterList_t *list, int useQuantifyVars)
7441{
7442  ClusterSortedList_t   *sortedList, *cur, *prev;
7443
7444  sortedList = ALLOC(ClusterSortedList_t, 1);
7445  sortedList->list = list;
7446
7447  if (!clusterSortedList) {
7448    sortedList->next = NIL(ClusterSortedList_t);
7449    return(sortedList);
7450  }
7451
7452  cur = clusterSortedList;
7453  prev = NIL(ClusterSortedList_t);
7454  while (cur) {
7455    if (list->flag == 2) {
7456      prev = cur;
7457      cur = cur->next;
7458      continue;
7459    }
7460    if (useQuantifyVars) {
7461      if (cur->list->flag == 2 ||
7462          list->nQuantifyVars < cur->list->nQuantifyVars ||
7463          (list->nQuantifyVars == cur->list->nQuantifyVars &&
7464           list->affinity >= cur->list->affinity)) {
7465        sortedList->next = cur;
7466        if (cur == clusterSortedList)
7467          clusterSortedList = sortedList;
7468        else
7469          prev->next = sortedList;
7470        break;
7471      }
7472    } else {
7473      if (cur->list->flag == 2 ||
7474          list->affinity > cur->list->affinity ||
7475          (list->affinity == cur->list->affinity &&
7476           list->nQuantifyVars <= cur->list->nQuantifyVars)) {
7477        sortedList->next = cur;
7478        if (cur == clusterSortedList)
7479          clusterSortedList = sortedList;
7480        else
7481          prev->next = sortedList;
7482        break;
7483      }
7484    }
7485    prev = cur;
7486    cur = cur->next;
7487  }
7488  if (!cur) {
7489    prev->next = sortedList;
7490    sortedList->next = NIL(ClusterSortedList_t);
7491  }
7492  return(clusterSortedList);
7493}
7494
7495
7496/**Function********************************************************************
7497
7498  Synopsis    [Returns the number of lists in a cluster list.]
7499
7500  Description [Returns the number of lists in a cluster list.]
7501
7502  SideEffects []
7503
7504******************************************************************************/
7505static int
7506CountClusterList(ClusterList_t *clusterList)
7507{
7508  ClusterList_t *list;
7509  int           n = 0;
7510
7511  list = clusterList;
7512  while (list) {
7513    if (list->flag == 3)
7514      break;
7515    n++;
7516    if (list->flag == 2)
7517      break;
7518    list = list->next;
7519  }
7520
7521  return(n);
7522}
7523
7524
7525/**Function********************************************************************
7526
7527  Synopsis    [Returns the number of lists in a sorted cluster list.]
7528
7529  Description [Returns the number of lists in a sorted cluster list.]
7530
7531  SideEffects []
7532
7533******************************************************************************/
7534static int
7535CountClusterSortedList(ClusterSortedList_t *clusterSortedList)
7536{
7537  ClusterSortedList_t   *sortedList;
7538  int                   n = 0;
7539
7540  sortedList = clusterSortedList;
7541  while (sortedList) {
7542    n++;
7543    sortedList = sortedList->next;
7544  }
7545
7546  return(n);
7547}
7548
7549
7550/**Function********************************************************************
7551
7552  Synopsis    [Creates an initial cluster using ARDC decomposition.]
7553
7554  Description [Creates an initial cluster using ARDC decomposition.]
7555
7556  SideEffects []
7557
7558******************************************************************************/
7559static array_t *
7560CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray,
7561                     ImgFunctionData_t *functionData, array_t *nsVarBddArray,
7562                     ImgTrmOption_t *option)
7563{
7564  array_t               *clusteredRelationArray;
7565  array_t               *partitionArray;
7566  Part_Subsystem_t      *partitionSubsystem;
7567  st_table              *vertexTable;
7568  int                   i, j;
7569  int                   mddId;
7570  long                  bddId;
7571  Ntk_Node_t            *latch;
7572  mdd_t                 *cluster, *product, *relation, *var;
7573  char                  *latchName;
7574  st_generator          *stGen;
7575  st_table              *id2relation;
7576  array_t               *bddIdArray;
7577  int                   nVars;
7578  char                  *nsVarFlag;
7579  array_t               *domainVars;
7580
7581  if (array_n(functionData->domainVars) == array_n(functionData->rangeVars))
7582    domainVars = functionData->domainVars;
7583  else {
7584    domainVars = array_alloc(int, 0);
7585    for (i = 0; i < array_n(functionData->rangeVars); i++) {
7586      mddId = array_fetch(int, functionData->domainVars, i);
7587      array_insert_last(int, domainVars, mddId);
7588    }
7589  }
7590  partitionArray = Fsm_ArdcDecomposeStateSpace(functionData->network,
7591                                                domainVars,
7592                                                functionData->roots,
7593                                                NIL(Fsm_ArdcOptions_t));
7594  if (domainVars != functionData->domainVars)
7595    array_free(domainVars);
7596
7597  nVars = bdd_num_vars(mddManager);
7598  nsVarFlag = ALLOC(char, nVars);
7599  memset(nsVarFlag, 0, sizeof(char) * nVars);
7600  for (i = 0; i < array_n(nsVarBddArray); i++) {
7601    var = array_fetch(mdd_t *, nsVarBddArray, i);
7602    bddId = (long) bdd_top_var_id(var);
7603    nsVarFlag[bddId] = 1;
7604  }
7605  clusteredRelationArray = array_alloc(mdd_t *, 0);
7606  id2relation = st_init_table(st_numcmp, st_numhash);
7607  for (i = 0; i < array_n(relationArray); i++) {
7608    relation = array_fetch(mdd_t *, relationArray, i);
7609    bddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
7610    for (j = 0; j < array_n(bddIdArray); j++) {
7611      bddId = (long) array_fetch(int, bddIdArray, j);
7612      if (nsVarFlag[bddId]) {
7613        st_insert(id2relation, (char *)bddId, (char *)relation);
7614        break;
7615      }
7616    }
7617
7618    /* the relation of intermediate variable */
7619    if (j == array_n(bddIdArray)) {
7620      array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
7621    }
7622
7623    array_free(bddIdArray);
7624  }
7625  FREE(nsVarFlag);
7626
7627  arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
7628    cluster = mdd_one(mddManager);
7629    vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
7630    st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
7631      latch = Ntk_NetworkFindNodeByName(functionData->network, latchName); 
7632      mddId = Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
7633      bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
7634      for (j = 0; j < array_n(bddIdArray); j++) {
7635        bddId = (long) array_fetch(int, bddIdArray, j);
7636        if (st_lookup(id2relation, (char *)bddId, &relation)) {
7637          st_delete(id2relation, &bddId, NULL);
7638          product = mdd_and(cluster, relation, 1, 1);
7639          mdd_free(cluster);
7640          cluster = product;
7641        }
7642      }
7643      array_free(bddIdArray);
7644    }
7645    Part_PartitionSubsystemFree(partitionSubsystem);
7646    array_insert_last(mdd_t *, clusteredRelationArray, cluster);
7647  }
7648  array_free(partitionArray);
7649
7650  st_foreach_item(id2relation, stGen, &bddId, &relation) {
7651    array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
7652  }
7653  st_free_table(id2relation);
7654
7655/*
7656  if (option->mlpDebug) {
7657    mdd_t       *tr1, *tr2, *tmp;
7658
7659    tr1 = mdd_one(mddManager);
7660    for (i = 0; i < array_n(relationArray); i++) {
7661      relation = array_fetch(mdd_t *, relationArray, i);
7662      tmp = mdd_and(tr1, relation, 1, 1);
7663      mdd_free(tr1);
7664      tr1 = tmp;
7665    }
7666
7667    tr2 = mdd_one(mddManager);
7668    for (i = 0; i < array_n(clusteredRelationArray); i++) {
7669      relation = array_fetch(mdd_t *, clusteredRelationArray, i);
7670      tmp = mdd_and(tr2, relation, 1, 1);
7671      mdd_free(tr2);
7672      tr2 = tmp;
7673    }
7674
7675    assert(mdd_equal(tr1, tr2));
7676    mdd_free(tr1);
7677    mdd_free(tr2);
7678  }
7679*/
7680
7681  return(clusteredRelationArray);
7682}
7683
7684
7685/**Function********************************************************************
7686
7687  Synopsis    [Updates matrix information properly.]
7688
7689  Description [Updates matrix information properly.]
7690
7691  SideEffects []
7692
7693******************************************************************************/
7694static void
7695SortCol(char **xy, int nRows, int nCols,
7696        RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder)
7697{
7698  int   x, y, i, j, row, col, lastVar;
7699  int   otherRow, otherCol;
7700
7701  lastVar = nCols - 1;
7702
7703  for (x = nRows - 1; x >= 0; x--) {
7704    row = rowOrder[x];
7705    for (y = lastVar; y >= 0; y--) {
7706      col = colOrder[y];
7707      if (colInfo[col].gMin == row) {
7708        if (y == lastVar) {
7709          lastVar--;
7710          continue;
7711        }
7712        for (j = y; j < lastVar; j++) {
7713          colOrder[j] = colOrder[j + 1];
7714          colInfo[colOrder[j]].pos = j;
7715        }
7716        colOrder[lastVar] = col;
7717        colInfo[col].pos = lastVar;
7718        for (i = x; i < nRows; i++) {
7719          otherRow = rowOrder[i];
7720          if (colInfo[rowInfo[otherRow].gMax].pos < lastVar)
7721            rowInfo[otherRow].gMax = col;
7722          if (rowInfo[otherRow].gMin == col) {
7723            for (j = 0; j < nCols; j++) {
7724              otherCol = colOrder[j];
7725              if (xy[otherRow][otherCol]) {
7726                rowInfo[otherRow].gMin = otherCol;
7727                break;
7728              }
7729            }
7730          }
7731        }
7732        lastVar--;
7733      }
7734    }
7735  }
7736}
7737
7738
7739/**Function********************************************************************
7740
7741  Synopsis    [Finds disappearing present state variables in a row.]
7742
7743  Description [Finds disappearing present state variables in a row.]
7744
7745  SideEffects []
7746
7747******************************************************************************/
7748static void
7749UpdateDisapearingPsVars(mdd_manager *mddManager, char **xy,
7750                        int nActiveRows, int nActiveCols,
7751                        int *rowOrder, int *colOrder,
7752                        RcInfo_t *rowInfo, RcInfo_t *colInfo,
7753                        int row, ImgTrmOption_t *option)
7754{
7755  int           i, id, x, y, s, t, col, tmpRow;
7756  mdd_t         *relation;
7757  array_t       *supportArray;
7758  char          *supportIndex;
7759  int           nVars;
7760
7761  nVars = bdd_num_vars(mddManager);
7762  relation = rowInfo[row].data.row.func;
7763  supportIndex = ALLOC(char, nVars);
7764  memset(supportIndex, 0, sizeof(char) * nVars);
7765  supportArray = mdd_get_bdd_support_ids(mddManager, relation);
7766  for (i = 0; i < array_n(supportArray); i++) {
7767    id = array_fetch(int, supportArray, i);
7768    supportIndex[id] = 1;
7769  }
7770  array_free(supportArray);
7771
7772  s = colInfo[rowInfo[row].gMin].pos;
7773  t = colInfo[rowInfo[row].gMax].pos;
7774  x = rowInfo[row].pos;
7775  rowInfo[row].gNum = 0;
7776  rowInfo[row].gMin = nActiveCols;
7777  rowInfo[row].gMax = -1;
7778  for (y = s; y <= t; y++) {
7779    col = colOrder[y];
7780    if (!xy[row][col])
7781      continue;
7782    id = (int)bdd_top_var_id(colInfo[col].data.col.var);
7783    if (supportIndex[id]) {
7784      rowInfo[row].gNum++;
7785      if (rowInfo[row].gMin == nActiveCols)
7786        rowInfo[row].gMin = col;
7787      rowInfo[row].gMax = col;
7788    } else {
7789      xy[row][col] = 0;
7790      if (colInfo[col].gNum == 1) {
7791        colInfo[col].gNum = 0;
7792        colInfo[col].gMin = nActiveRows;
7793        colInfo[col].gMax = -1;
7794      } else if (colInfo[col].gNum == 2) {
7795        colInfo[col].gNum = 1;
7796        if (colInfo[col].gMin == row)
7797          colInfo[col].gMin = colInfo[col].gMax;
7798        else
7799          colInfo[col].gMax = colInfo[col].gMin;
7800      } else {
7801        colInfo[col].gNum--;
7802        if (row == colInfo[col].gMin) {
7803          for (i = x + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
7804            tmpRow = rowOrder[i];
7805            if (xy[tmpRow][col]) {
7806              colInfo[col].gMin = tmpRow;
7807              break;
7808            }
7809          }
7810        } else if (row == colInfo[col].gMax) {
7811          for (i = x - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
7812            tmpRow = rowOrder[i];
7813            if (xy[tmpRow][col]) {
7814              colInfo[col].gMax = tmpRow;
7815              break;
7816            }
7817          }
7818        }
7819      }
7820    }
7821  }
7822
7823  FREE(supportIndex);
7824}
7825
7826
7827/**Function********************************************************************
7828
7829  Synopsis    [Finds disappearing present state variables in a cluster.]
7830
7831  Description [Finds disappearing present state variables in a cluster.]
7832
7833  SideEffects []
7834
7835******************************************************************************/
7836static void
7837UpdateDisapearingPsVarsInCluster(mdd_manager *mddManager, char **xy,
7838                        int nActiveRows, int nActiveCols,
7839                        int *rowOrder, int *colOrder,
7840                        RcInfo_t *rowInfo, RcInfo_t *colInfo,
7841                        ClusterList_t *list, int moveFlag,
7842                        ImgTrmOption_t *option)
7843{
7844  int           i, j, k, y, id, row, col, otherRow, otherCol;
7845  int           s1, t1, s2, t2, s3, t3, t4;
7846  mdd_t         *relation;
7847  array_t       *supportArray;
7848  char          *supportIndex;
7849  int           nVars;
7850  ClusterList_t *otherList;
7851
7852  if (list->nSupports == 0)
7853    return;
7854
7855  nVars = bdd_num_vars(mddManager);
7856  relation = list->product;
7857  supportIndex = ALLOC(char, nVars);
7858  memset(supportIndex, 0, sizeof(char) * nVars);
7859  supportArray = mdd_get_bdd_support_ids(mddManager, relation);
7860  for (i = 0; i < array_n(supportArray); i++) {
7861    id = array_fetch(int, supportArray, i);
7862    supportIndex[id] = 1;
7863  }
7864  array_free(supportArray);
7865
7866  s1 = colInfo[list->minCol].pos;
7867  t1 = colInfo[list->maxCol].pos;
7868  for (y = t1; y >= s1; y--) {
7869    col = colOrder[y];
7870    if (!list->supports[col])
7871      continue;
7872    id = (int)bdd_top_var_id(colInfo[col].data.col.var);
7873    if (!supportIndex[id]) {
7874      list->nSupports--;
7875      list->supports[col] = 0;
7876      if (list->nSupports == 0) {
7877        list->minCol = -1;
7878        list->maxCol = -1;
7879      } else if (list->nSupports == 1) {
7880        if (list->minCol == col)
7881          list->minCol = list->maxCol;
7882        else
7883          list->maxCol = list->minCol;
7884      } else if (list->nSupports > 1) {
7885        if (list->minCol == col) {
7886          for (j = y + 1; j <= t1; j++) {
7887            otherCol = colOrder[j];
7888            if (list->supports[otherCol]) {
7889              list->minCol = otherCol;
7890              break;
7891            }
7892          }
7893        } else if (list->maxCol == col) {
7894          for (j = y - 1; j >= s1; j--) {
7895            otherCol = colOrder[j];
7896            if (list->supports[otherCol]) {
7897              list->maxCol = otherCol;
7898              break;
7899            }
7900          }
7901        }
7902      }
7903
7904      for (j = list->start; j <= list->end; j++) {
7905        row = rowOrder[j];
7906        if (xy[row][col]) {
7907          xy[row][col] = 0;
7908          colInfo[col].gNum--;
7909          rowInfo[row].gNum--;
7910          if (rowInfo[row].gNum > 0) {
7911            s2 = colInfo[rowInfo[row].gMin].pos;
7912            t2 = colInfo[rowInfo[row].gMax].pos;
7913            if (rowInfo[row].gMin == col) {
7914              for (k = y + 1; k <= t2; k++) {
7915                otherCol = colOrder[k];
7916                if (xy[row][otherCol]) {
7917                  rowInfo[row].gMin = otherCol;
7918                  break;
7919                }
7920              }
7921            } else if (rowInfo[row].gMax == col) {
7922              for (k = y - 1; k >= s2; k--) {
7923                otherCol = colOrder[k];
7924                if (xy[row][otherCol]) {
7925                  rowInfo[row].gMax = otherCol;
7926                  break;
7927                }
7928              }
7929            }
7930          } else {
7931            rowInfo[row].gMin = -1;
7932            rowInfo[row].gMax = nActiveCols;
7933          }
7934        }
7935      }
7936
7937      if (colInfo[col].gNum == 0) {
7938        colInfo[col].lNum = 0;
7939        colInfo[col].gMin = nActiveRows;
7940        colInfo[col].lMin = nActiveRows;
7941        colInfo[col].gMax = -1;
7942        colInfo[col].lMax = -1;
7943      } else if (colInfo[col].gNum == 1) {
7944        colInfo[col].lNum = 1;
7945        if (rowInfo[colInfo[col].gMax].pos > list->end) {
7946          colInfo[col].gMin = colInfo[col].gMax;
7947          colInfo[col].lMin = colInfo[col].gMax;
7948        } else {
7949          colInfo[col].gMax = colInfo[col].gMin;
7950          colInfo[col].lMax = colInfo[col].gMin;
7951        }
7952      } else {
7953        colInfo[col].lNum = colInfo[col].gNum;
7954        if (rowInfo[colInfo[col].gMin].pos >= list->start &&
7955            rowInfo[colInfo[col].gMin].pos <= list->end) {
7956          for (i = list->end + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
7957            otherRow = rowOrder[i];
7958            if (xy[otherRow][col]) {
7959              colInfo[col].gMin = otherRow;
7960              colInfo[col].lMin = otherRow;
7961              break;
7962            }
7963          }
7964        } else if (rowInfo[colInfo[col].gMax].pos >= list->start &&
7965                   rowInfo[colInfo[col].gMax].pos <= list->end) {
7966          for (i = list->start - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
7967            otherRow = rowOrder[i];
7968            if (xy[otherRow][col]) {
7969              colInfo[col].gMax = otherRow;
7970              colInfo[col].lMax = otherRow;
7971              break;
7972            }
7973          }
7974        }
7975      }
7976
7977      if (moveFlag) {
7978        if (colInfo[col].gNum == 0) {
7979          if (y < nActiveCols - 1) {
7980            for (j = y; j < nActiveCols - 1; j++) {
7981              colOrder[j] = colOrder[j + 1];
7982              colInfo[colOrder[j]].pos = j;
7983            }
7984            colOrder[nActiveCols - 1] = col;
7985            colInfo[col].pos = nActiveCols - 1;
7986          }
7987        } else if (rowInfo[colInfo[col].gMin].pos > list->end) {
7988          if (list->prev && list->prev->start > list->start) {
7989            /* Image */
7990            otherList = list->prev;
7991            while (!otherList->supports[col])
7992              otherList = otherList->prev;
7993          } else if (list->next && list->next->start > list->start) {
7994            /* Preimage */
7995            otherList = list->next;
7996            while (!otherList->supports[col])
7997              otherList = otherList->next;
7998          } else
7999            otherList = NIL(ClusterList_t);
8000
8001          if (otherList) {
8002            t2 = colInfo[otherList->maxCol].pos;
8003            if (y != t2) {
8004              for (j = y; j < t2; j++) {
8005                colOrder[j] = colOrder[j + 1];
8006                colInfo[colOrder[j]].pos = j;
8007              }
8008              colOrder[t2] = col;
8009              colInfo[col].pos = t2;
8010              otherList->maxCol = col;
8011              if (otherList->minCol == col) {
8012                for (j = y; j < t2; j++) {
8013                  otherCol = colOrder[j];
8014                  if (otherList->supports[otherCol]) {
8015                    otherList->minCol = otherCol;
8016                    break;
8017                  }
8018                }
8019              }
8020
8021              s3 = rowInfo[colInfo[col].gMin].pos;
8022              t3 = rowInfo[colInfo[col].gMax].pos;
8023              for (j = s3; j <= t3; j++) {
8024                otherRow = rowOrder[j];
8025                if (xy[otherRow][col]) {
8026                  if (rowInfo[otherRow].gNum > 1) {
8027                    t4 = colInfo[rowInfo[otherRow].gMax].pos;
8028                    if (t4 <= t2)
8029                      rowInfo[otherRow].gMax = col;
8030                    if (rowInfo[otherRow].gMin == col) {
8031                      for (k = y; k <= t4; k++) {
8032                        otherCol = colOrder[k];
8033                        if (xy[otherRow][otherCol]) {
8034                          rowInfo[otherRow].gMin = col;
8035                          break;
8036                        }
8037                      }
8038                    }
8039                  }
8040                }
8041              }
8042            }
8043          }
8044        }
8045      }
8046
8047      if (option->mlpDebug) {
8048        CheckCluster(list, nActiveCols, colInfo, colOrder);
8049        CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
8050                    rowInfo, colInfo, rowOrder, colOrder,
8051                    0, nActiveRows - 1, 0, nActiveCols - 1, 0);
8052      }
8053    }
8054  }
8055
8056  FREE(supportIndex);
8057}
8058
8059
8060/**Function********************************************************************
8061
8062  Synopsis    [Finds non-appearing next state variables.]
8063
8064  Description [Finds non-appearing next state variables.]
8065
8066  SideEffects []
8067
8068******************************************************************************/
8069static void
8070UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray,
8071                        int nRows, RcInfo_t *rowInfo, int *rowOrder,
8072                        array_t *nonAppearingVarBddArray)
8073{
8074  int           i, j, k, row, index, nVars;
8075  mdd_t         *nsVar, *relation;
8076  char          *existFlag;
8077  array_t       *supportArray, *tmpArray;
8078
8079  nVars = bdd_num_vars(mddManager);
8080  existFlag = ALLOC(char, nVars);
8081  memset(existFlag, 0, sizeof(char) * nVars);
8082
8083  for (i = 0; i < nRows; i++) {
8084    row = rowOrder[i];
8085    relation = rowInfo[row].data.row.func;
8086    supportArray = mdd_get_bdd_support_ids(mddManager, relation);
8087    for (j = 0; j < array_n(supportArray); j++) {
8088      index = array_fetch(int, supportArray, j);
8089      existFlag[index] = 1;
8090    }
8091    array_free(supportArray);
8092  }
8093
8094  for (i = 0; i < nRows; i++) {
8095    row = rowOrder[i];
8096    for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
8097      nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
8098      index = (int)bdd_top_var_id(nsVar);
8099      if (!existFlag[index]) {
8100        tmpArray = array_alloc(mdd_t *, 0);
8101        for (k = 0; k < j; k++) {
8102          nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
8103          array_insert_last(mdd_t *, tmpArray, nsVar);
8104        }
8105        for (k = j + 1; k < array_n(rowInfo[row].data.row.nsVarBddArray); k++) {
8106          nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
8107          index = (int)bdd_top_var_id(nsVar);
8108          if (existFlag[index])
8109            array_insert_last(mdd_t *, tmpArray, nsVar);
8110        }
8111        array_free(rowInfo[row].data.row.nsVarBddArray);
8112        rowInfo[row].data.row.nsVarBddArray = tmpArray;
8113        break;
8114      }
8115    }
8116  }
8117
8118  for (i = 0; i < array_n(nsVarBddArray); i++) {
8119    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
8120    index = (int)bdd_top_var_id(nsVar);
8121    if (!existFlag[index])
8122      array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
8123  }
8124
8125  FREE(existFlag);
8126}
8127
8128
8129/**Function********************************************************************
8130
8131  Synopsis    [Writes variable order in coulumn of the matrix.]
8132
8133  Description [Writes variable order in coulumn of the matrix.]
8134
8135  SideEffects []
8136
8137******************************************************************************/
8138static void
8139WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo)
8140{
8141  int   i, col;
8142  mdd_t *var;
8143  char  *name;
8144
8145  for (i = 0; i < nCols; i++) {
8146    col = colOrder[i];
8147    var = colInfo[col].data.col.var;
8148    name = mdd_read_var_name(var);
8149    fprintf(fout, "%s\n", name);
8150  }
8151}
Note: See TracBrowser for help on using the repository browser.