VIS

src/img/imgTfmFwd.c

Go to the documentation of this file.
00001 
00035 #include "imgInt.h"
00036 
00037 static char rcsid[] UNUSED = "$Id: imgTfmFwd.c,v 1.37 2005/04/22 19:45:46 jinh Exp $";
00038 
00039 /*---------------------------------------------------------------------------*/
00040 /* Constant declarations                                                     */
00041 /*---------------------------------------------------------------------------*/
00042 
00043 /*---------------------------------------------------------------------------*/
00044 /* Type declarations                                                         */
00045 /*---------------------------------------------------------------------------*/
00046 
00047 /*---------------------------------------------------------------------------*/
00048 /* Structure declarations                                                    */
00049 /*---------------------------------------------------------------------------*/
00050 
00051 /*---------------------------------------------------------------------------*/
00052 /* Variable declarations                                                     */
00053 /*---------------------------------------------------------------------------*/
00054 
00055 /*---------------------------------------------------------------------------*/
00056 /* Macro declarations                                                        */
00057 /*---------------------------------------------------------------------------*/
00058 
00061 /*---------------------------------------------------------------------------*/
00062 /* Static function prototypes                                                */
00063 /*---------------------------------------------------------------------------*/
00064 
00065 static mdd_t * ImageByInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, mdd_t *from, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int splitMethod, int turnDepth, int depth);
00066 static mdd_t * ImageByStaticInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, int turnDepth, int depth);
00067 static mdd_t * ImageByOutputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, int depth);
00068 static int ImageDecomposeAndChooseSplitVar(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, int splitMethod, int split, int piSplitFlag, array_t *vectorArray, array_t *varArray, mdd_t **singles, array_t *relationArray, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube);
00069 static mdd_t * ImageFast2(ImgTfmInfo_t *info, array_t *vector);
00070 static int FindDecomposableVariable(ImgTfmInfo_t *info, array_t *vector);
00071 static int TfmCheckImageValidity(ImgTfmInfo_t *info, mdd_t *image);
00072 static void FindIntermediateSupport(array_t *vector, ImgComponent_t *comp, int nVars, int nGroups, int *stack, char *stackFlag, int *funcGroup, int *size, char *intermediateVarFlag, int *intermediateVarFuncMap);
00073 static void PrintVectorDecomposition(ImgTfmInfo_t *info, array_t *vectorArray, array_t *varArray);
00074 static int CheckIfValidSplitOrGetNew(ImgTfmInfo_t *info, int split, array_t *vector, array_t *relationArray, mdd_t *from);
00075 static int ChooseInputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, int splitMethod, int decompose, int piSplitFlag, int *varOccur);
00076 static int ChooseOutputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, int splitMethod);
00077 
00081 /*---------------------------------------------------------------------------*/
00082 /* Definition of exported functions                                          */
00083 /*---------------------------------------------------------------------------*/
00084 
00085 
00086 /*---------------------------------------------------------------------------*/
00087 /* Definition of internal functions                                          */
00088 /*---------------------------------------------------------------------------*/
00089 
00090 
00100 mdd_t *
00101 ImgTfmImage(ImgTfmInfo_t *info, mdd_t *from)
00102 {
00103   mdd_t         *res, *r, *cube, *newFrom, *one;
00104   array_t       *newVector, *depVector;
00105   int           splitMethod, turnDepth;
00106   mdd_t         *refResult;
00107   array_t       *relationArray, *newRelationArray, *tmpRelationArray;
00108   int           eliminateDepend;
00109   int           partial, saveUseConstraint;
00110   long          size1, size2;
00111   mdd_t         *cofactorCube, *abstractCube;
00112   int           i, maxDepth, size, nDependVars;
00113 
00114   info->maxIntermediateSize = 0;
00115   if (info->eliminateDepend == 1 ||
00116       (info->eliminateDepend == 2 && info->nPrevEliminatedFwd > 0)) {
00117     eliminateDepend = 1;
00118   } else
00119     eliminateDepend = 0;
00120 
00121   saveUseConstraint = info->useConstraint;
00122   if (info->buildTR) {
00123     if (eliminateDepend == 0 &&
00124         info->option->splitMethod == 3 &&
00125         info->option->splitMaxDepth < 0 &&
00126         info->option->buildPartialTR == FALSE &&
00127         info->option->rangeComp == 0 &&
00128         info->option->findEssential == FALSE) {
00129       r = ImgBddLinearAndSmooth(info->manager, from,
00130                       info->fwdClusteredRelationArray,
00131                       info->fwdArraySmoothVarBddArray,
00132                       info->fwdSmoothVarCubeArray,
00133                       info->option->verbosity);
00134       res = ImgSubstitute(r, info->functionData, Img_R2D_c);
00135       mdd_free(r);
00136       return(res);
00137     }
00138     relationArray = mdd_array_duplicate(info->fwdClusteredRelationArray);
00139   } else
00140     relationArray = NIL(array_t);
00141   if (info->useConstraint == 1 ||
00142       (info->useConstraint == 2 &&
00143        info->nImageComps == info->option->rangeTryThreshold)) {
00144     if (info->buildTR == 2) {
00145       newVector = NIL(array_t);
00146       cube = mdd_one(info->manager);
00147       if (eliminateDepend) {
00148         newFrom = ImgTrmEliminateDependVars(info->functionData, relationArray,
00149                                             from, NIL(mdd_t *), &nDependVars);
00150         if (nDependVars) {
00151           if (info->option->verbosity > 0)
00152             (void)fprintf(vis_stdout, "Eliminated %d vars.\n", nDependVars);
00153           info->averageFoundDependVars = (info->averageFoundDependVars *
00154                     (float)info->nFoundDependVars + (float)nDependVars) /
00155                     (float)(info->nFoundDependVars + 1);
00156           info->nFoundDependVars++;
00157         }
00158 
00159         info->nPrevEliminatedFwd = nDependVars;
00160       } else
00161         newFrom = from;
00162       cofactorCube = NIL(mdd_t);
00163       abstractCube = NIL(mdd_t);
00164     } else {
00165       newVector = ImgVectorCopy(info, info->vector);
00166       cube = mdd_one(info->manager);
00167       if (eliminateDepend) {
00168         newFrom = ImgTfmEliminateDependVars(info, newVector, relationArray,
00169                                             from, NIL(array_t *), NIL(mdd_t *));
00170       } else
00171         newFrom = from;
00172       if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
00173         cofactorCube = mdd_one(info->manager);
00174         abstractCube = mdd_one(info->manager);
00175       } else {
00176         cofactorCube = NIL(mdd_t);
00177         abstractCube = NIL(mdd_t);
00178       }
00179     }
00180   } else {
00181     if (eliminateDepend) {
00182       depVector = ImgVectorCopy(info, info->vector);
00183       newFrom = ImgTfmEliminateDependVars(info, depVector, relationArray, from,
00184                                           NIL(array_t *), NIL(mdd_t *));
00185       /* constrain delta w.r.t. from here */
00186       if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
00187         ImgVectorConstrain(info, depVector, newFrom, relationArray,
00188                            &newVector, &cube, &newRelationArray, &cofactorCube,
00189                            &abstractCube, FALSE);
00190       } else if (relationArray) {
00191         ImgVectorConstrain(info, depVector, newFrom, relationArray,
00192                            &newVector, &cube, NIL(array_t *), &cofactorCube,
00193                            &abstractCube, FALSE);
00194         newRelationArray = NIL(array_t);
00195       } else {
00196         ImgVectorConstrain(info, depVector, newFrom, NIL(array_t),
00197                            &newVector, &cube, NIL(array_t *), NIL(mdd_t *),
00198                            NIL(mdd_t *), FALSE);
00199         newRelationArray = NIL(array_t);
00200         cofactorCube = NIL(mdd_t);
00201         abstractCube = NIL(mdd_t);
00202       }
00203 
00204       if (info->useConstraint == 2) {
00205         size1 = ImgVectorBddSize(depVector);
00206         size2 = ImgVectorBddSize(newVector);
00207         if (info->option->rangeCheckReorder) {
00208           bdd_reorder(info->manager);
00209           size1 = ImgVectorBddSize(depVector);
00210           size2 = ImgVectorBddSize(newVector);
00211         }
00212         if (size2 > size1 * info->option->rangeThreshold) { /* cancel */
00213           if (info->option->verbosity)
00214             fprintf(vis_stdout, "** tfm info: canceled range computation.\n");
00215           info->useConstraint = 1;
00216           ImgVectorFree(newVector);
00217           newVector = depVector;
00218           mdd_free(cube);
00219           cube = mdd_one(info->manager);
00220           if (newRelationArray && newRelationArray != relationArray)
00221             mdd_array_free(newRelationArray);
00222           if (cofactorCube) {
00223             mdd_free(cofactorCube);
00224             cofactorCube = mdd_one(info->manager);
00225           }
00226           if (abstractCube) {
00227             mdd_free(abstractCube);
00228             abstractCube = mdd_one(info->manager);
00229           }
00230           info->nImageComps++;
00231         } else {
00232           info->useConstraint = 0;
00233           info->nImageComps = 0;
00234           info->nRangeComps++;
00235         }
00236       }
00237       if (info->useConstraint == 0)
00238         ImgVectorFree(depVector);
00239     } else {
00240       newFrom = from;
00241       /* constrain delta w.r.t. from here */
00242       if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
00243         ImgVectorConstrain(info, info->vector, newFrom, relationArray,
00244                            &newVector, &cube, &newRelationArray, &cofactorCube,
00245                            &abstractCube, FALSE);
00246         if (info->option->debug) {
00247           refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
00248           res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), NIL(mdd_t),
00249                                                 newRelationArray,
00250                                                 cofactorCube, abstractCube);
00251           assert(mdd_equal(refResult, res));
00252           mdd_free(refResult);
00253           mdd_free(res);
00254         }
00255       } else if (relationArray) {
00256         ImgVectorConstrain(info, info->vector, newFrom, relationArray,
00257                            &newVector, &cube, NIL(array_t *), &cofactorCube,
00258                            &abstractCube, FALSE);
00259         newRelationArray = NIL(array_t);
00260       } else {
00261         ImgVectorConstrain(info, info->vector, newFrom, NIL(array_t),
00262                            &newVector, &cube, NIL(array_t *), NIL(mdd_t *),
00263                            NIL(mdd_t *), FALSE);
00264         newRelationArray = NIL(array_t);
00265         cofactorCube = NIL(mdd_t);
00266         abstractCube = NIL(mdd_t);
00267       }
00268 
00269       if (info->useConstraint == 2) {
00270         size1 = ImgVectorBddSize(info->vector);
00271         size2 = ImgVectorBddSize(newVector);
00272         if (info->option->rangeCheckReorder) {
00273           bdd_reorder(info->manager);
00274           size1 = ImgVectorBddSize(info->vector);
00275           size2 = ImgVectorBddSize(newVector);
00276         }
00277         if (size2 > size1 * info->option->rangeThreshold) { /* cancel */
00278           if (info->option->verbosity)
00279             fprintf(vis_stdout, "** tfm info: canceled range computation.\n");
00280           info->useConstraint = 1;
00281           ImgVectorFree(newVector);
00282           newVector = info->vector;
00283           mdd_free(cube);
00284           cube = mdd_one(info->manager);
00285           if (newRelationArray && newRelationArray != relationArray)
00286             mdd_array_free(newRelationArray);
00287           if (cofactorCube) {
00288             mdd_free(cofactorCube);
00289             cofactorCube = mdd_one(info->manager);
00290           }
00291           if (abstractCube) {
00292             mdd_free(abstractCube);
00293             abstractCube = mdd_one(info->manager);
00294           }
00295           info->nImageComps++;
00296         } else {
00297           info->useConstraint = 0;
00298           info->nImageComps = 0;
00299           info->nRangeComps++;
00300         }
00301       }
00302     }
00303     if (info->useConstraint == 0 && relationArray) {
00304       if (!newRelationArray) {
00305         if (bdd_is_tautology(cofactorCube, 1) &&
00306             bdd_is_tautology(abstractCube, 1)) {
00307           newRelationArray = ImgGetConstrainedRelationArray(info, relationArray,
00308                                                             newFrom);
00309         } else {
00310           tmpRelationArray = ImgGetConstrainedRelationArray(info, relationArray,
00311                                                             newFrom);
00312           newRelationArray = ImgGetCofactoredAbstractedRelationArray(
00313                                         info->manager, tmpRelationArray,
00314                                         cofactorCube, abstractCube);
00315           if (info->option->debug) {
00316             array_t     *tmpVector;
00317 
00318             tmpVector = ImgGetConstrainedVector(info, info->vector, newFrom);
00319             if (info->option->checkEquivalence) {
00320               assert(ImgCheckEquivalence(info, tmpVector, tmpRelationArray,
00321                                          NIL(mdd_t), NIL(mdd_t), 0));
00322             }
00323             refResult = ImgImageByHybrid(info, tmpVector, NIL(mdd_t));
00324             ImgVectorFree(tmpVector);
00325             res = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
00326                                                   NIL(mdd_t),
00327                                                   tmpRelationArray,
00328                                                   NIL(mdd_t), NIL(mdd_t));
00329             assert(mdd_equal(refResult, res));
00330             mdd_free(refResult);
00331             mdd_free(res);
00332           }
00333           mdd_array_free(tmpRelationArray);
00334         }
00335         mdd_free(cofactorCube);
00336         cofactorCube = NIL(mdd_t);
00337         mdd_free(abstractCube);
00338         abstractCube = NIL(mdd_t);
00339         if (info->option->debug) {
00340           refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
00341           res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), NIL(mdd_t),
00342                                                 newRelationArray,
00343                                                 NIL(mdd_t), NIL(mdd_t));
00344           assert(mdd_equal(refResult, res));
00345           mdd_free(refResult);
00346           mdd_free(res);
00347 
00348           if (info->nIntermediateVars) {
00349             mdd_t       *tmp;
00350 
00351             refResult = ImgImageByHybrid(info, info->vector, newFrom);
00352             res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), newFrom,
00353                                                   relationArray,
00354                                                   NIL(mdd_t), NIL(mdd_t));
00355             assert(mdd_equal(refResult, res));
00356             mdd_free(res);
00357             tmp = ImgImageByHybrid(info, newVector, NIL(mdd_t));
00358             res = mdd_and(tmp, cube, 1, 1);
00359             if (info->option->verbosity) {
00360               size = bdd_size(res);
00361               if (size > info->maxIntermediateSize)
00362                 info->maxIntermediateSize = size;
00363               if (info->option->printBddSize) {
00364                 fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
00365                         bdd_size(tmp), bdd_size(cube), size);
00366               }
00367             }
00368             mdd_free(tmp);
00369             assert(mdd_equal(refResult, res));
00370             mdd_free(refResult);
00371             mdd_free(res);
00372           }
00373         }
00374       }
00375       if (relationArray != newRelationArray) {
00376         mdd_array_free(relationArray);
00377         relationArray = newRelationArray;
00378       }
00379     }
00380     if (info->option->checkEquivalence) {
00381       assert(ImgCheckEquivalence(info, newVector, newRelationArray,
00382                                   NIL(mdd_t), NIL(mdd_t), 0));
00383     }
00384   }
00385   partial = 0;
00386   one = mdd_one(info->manager);
00387   splitMethod = info->option->splitMethod;
00388   if (splitMethod == 0) {
00389     r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
00390                           NIL(mdd_t), NIL(mdd_t), 0, 0, 0);
00391   } else if (splitMethod == 1)
00392     r = ImageByOutputSplit(info, newVector, one, 0);
00393   else {
00394     if (info->option->splitMethod == 0)
00395       turnDepth = info->nVars + 1;
00396     else
00397       turnDepth = info->option->turnDepth;
00398     if (turnDepth == 0) {
00399       if (splitMethod == 2)
00400         r = ImageByOutputSplit(info, newVector, one, 0);
00401       else {
00402         if (info->useConstraint && info->buildTR == 2) {
00403           if (info->buildPartialTR) {
00404             r = ImgImageByHybridWithStaticSplit(info, newVector, newFrom,
00405                                                 relationArray,
00406                                                 NIL(mdd_t), NIL(mdd_t));
00407           } else {
00408             r = ImgImageByHybridWithStaticSplit(info, NIL(array_t), newFrom,
00409                                                 relationArray,
00410                                                 NIL(mdd_t), NIL(mdd_t));
00411           }
00412         } else
00413           r = ImgImageByHybrid(info, newVector, newFrom);
00414       }
00415     } else if (splitMethod == 2) {
00416       r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
00417                                 NIL(mdd_t), NIL(mdd_t),
00418                                 splitMethod, turnDepth, 0);
00419     } else {
00420       if (info->useConstraint) {
00421         if (info->buildTR) {
00422           if (info->buildTR == 2) {
00423             if (info->buildPartialTR) {
00424               r = ImageByStaticInputSplit(info, newVector, newFrom,
00425                                           relationArray, turnDepth, 0);
00426               partial = 1;
00427             } else {
00428               r = ImageByStaticInputSplit(info, NIL(array_t), newFrom,
00429                                           relationArray, turnDepth, 0);
00430             }
00431           } else if (info->option->delayedSplit) {
00432             r = ImageByInputSplit(info, newVector, one, newFrom, relationArray,
00433                                   cofactorCube, abstractCube,
00434                                   splitMethod, turnDepth, 0);
00435           } else {
00436             r = ImageByInputSplit(info, newVector, one, newFrom, relationArray,
00437                                   NIL(mdd_t), NIL(mdd_t),
00438                                   splitMethod, turnDepth, 0);
00439           }
00440         } else {
00441           r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
00442                                 NIL(mdd_t), NIL(mdd_t),
00443                                 splitMethod, turnDepth, 0);
00444         }
00445       } else if (info->buildTR == 1 && info->option->delayedSplit) {
00446         r = ImageByInputSplit(info, newVector, one, NIL(mdd_t), relationArray,
00447                                 cofactorCube, abstractCube,
00448                                 splitMethod, turnDepth, 0);
00449       } else {
00450         r = ImageByInputSplit(info, newVector, one, NIL(mdd_t), relationArray,
00451                                 NIL(mdd_t), NIL(mdd_t),
00452                                 splitMethod, turnDepth, 0);
00453       }
00454     }
00455   }
00456   info->useConstraint = saveUseConstraint;
00457   if (relationArray &&
00458       !(info->option->debug && (partial || info->buildTR == 2))) {
00459     mdd_array_free(relationArray);
00460   }
00461   if (info->imgCache && info->option->autoFlushCache == 1)
00462     ImgFlushCache(info->imgCache);
00463   mdd_free(one);
00464   if (cofactorCube)
00465     mdd_free(cofactorCube);
00466   if (abstractCube)
00467     mdd_free(abstractCube);
00468   if (newFrom && newFrom != from)
00469     mdd_free(newFrom);
00470   res = bdd_and(r, cube, 1, 1);
00471   if (info->option->verbosity) {
00472     size = bdd_size(res);
00473     if (size > info->maxIntermediateSize)
00474       info->maxIntermediateSize = size;
00475     if (info->option->printBddSize) {
00476       fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
00477               bdd_size(r), bdd_size(cube), size);
00478     }
00479   }
00480   mdd_free(r);
00481   mdd_free(cube);
00482   if (newVector != info->vector)
00483     ImgVectorFree(newVector);
00484 
00485   if (info->option->debug) {
00486     if (info->buildTR == 2) {
00487       refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00488                                                   relationArray,
00489                                                   NIL(mdd_t), NIL(mdd_t));
00490       mdd_array_free(relationArray);
00491     } else {
00492       if (partial) {
00493         refResult = ImgImageByHybrid(info, info->fullVector, from);
00494         assert(mdd_equal(refResult, res));
00495         mdd_free(refResult);
00496         refResult = ImgImageByHybridWithStaticSplit(info, info->vector, from,
00497                                                     relationArray,
00498                                                     NIL(mdd_t), NIL(mdd_t));
00499         mdd_array_free(relationArray);
00500       } else
00501         refResult = ImgImageByHybrid(info, info->vector, from);
00502     }
00503     assert(mdd_equal(refResult, res));
00504     mdd_free(refResult);
00505   }
00506   if (info->option->findEssential)
00507     info->lastFoundEssentialDepth = info->foundEssentialDepth;
00508   if (info->option->printEssential == 2) {
00509     maxDepth = info->maxDepth < IMG_TF_MAX_PRINT_DEPTH ?
00510                 info->maxDepth : IMG_TF_MAX_PRINT_DEPTH;
00511     fprintf(vis_stdout, "foundEssential:");
00512     for (i = 0; i < maxDepth; i++)
00513       fprintf(vis_stdout, " [%d]%d", i, info->foundEssentials[i]);
00514     fprintf(vis_stdout, "\n");
00515   }
00516   if (info->option->verbosity) {
00517     fprintf(vis_stdout, "** tfm info: max intermediate BDD size = %d\n",
00518             info->maxIntermediateSize);
00519   }
00520   if (info->option->debug)
00521     assert(TfmCheckImageValidity(info, res));
00522   return(res);
00523 }
00524 
00525 
00535 mdd_t *
00536 ImgChooseTrSplitVar(ImgTfmInfo_t *info, array_t *vector,
00537                     array_t *relationArray, int trSplitMethod, int piSplitFlag)
00538 {
00539   int                   i, j, nVars;
00540   ImgComponent_t        *comp;
00541   char                  *support;
00542   int                   *varCost, bestCost = 0;
00543   int                   id, split;
00544   mdd_t                 *var, *relation;
00545 
00546   nVars = info->nVars;
00547   varCost = ALLOC(int, nVars);
00548   memset(varCost, 0, sizeof(int) * nVars);
00549 
00550   if (trSplitMethod == 0) {
00551     if (vector) {
00552       for (i = 0; i < array_n(vector); i++) {
00553         comp = array_fetch(ImgComponent_t *, vector, i);
00554         support = comp->support;
00555         for (j = 0; j < nVars; j++) {
00556           if (support[j])
00557             varCost[j]++;
00558         }
00559       }
00560     }
00561     comp = ImgComponentAlloc(info);
00562     support = comp->support;
00563     for (i = 0; i < array_n(relationArray); i++) {
00564       relation = array_fetch(mdd_t *, relationArray, i);
00565       comp->func = relation;
00566       ImgSupportClear(info, comp->support);
00567       ImgComponentGetSupport(comp);
00568       for (j = 0; j < nVars; j++) {
00569         if (support[j])
00570           varCost[j]++;
00571       }
00572     }
00573     comp->func = NIL(mdd_t);
00574     ImgComponentFree(comp);
00575   } else {
00576     for (i = 0; i < array_n(info->domainVarBddArray); i++) {
00577       var = array_fetch(mdd_t *, info->domainVarBddArray, i);
00578       id = (int)bdd_top_var_id(var);
00579       if (vector) {
00580         for (j = 0; j < array_n(vector); j++) {
00581           comp = array_fetch(ImgComponent_t *, vector, j);
00582           varCost[id] += bdd_estimate_cofactor(comp->func, var, 1);
00583           varCost[id] += bdd_estimate_cofactor(comp->func, var, 0);
00584         }
00585       }
00586       for (j = 0; j < array_n(relationArray); j++) {
00587         relation = array_fetch(mdd_t *, relationArray, j);
00588         varCost[id] += bdd_estimate_cofactor(relation, var, 1);
00589         varCost[id] += bdd_estimate_cofactor(relation, var, 0);
00590       }
00591       varCost[id] = IMG_TF_MAX_INT - varCost[id];
00592     }
00593   }
00594 
00595   split = -1;
00596   for (i = 0; i < nVars; i++) {
00597     if (varCost[i] == 0)
00598       continue;
00599     if (!piSplitFlag) {
00600       if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
00601         continue;
00602     }
00603     if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
00604       continue;
00605     if (info->intermediateVarsTable &&
00606         st_lookup(info->intermediateVarsTable, (char *)(long)i, NIL(char *))) {
00607       continue;
00608     }
00609 
00610     if (split == -1 || varCost[i] > bestCost) {
00611       bestCost = varCost[i];
00612       split = i;
00613     }
00614   }
00615   FREE(varCost);
00616   if (split == -1)
00617     return(NIL(mdd_t));
00618   var = bdd_var_with_index(info->manager, split);
00619   return(var);
00620 }
00621 
00622 
00623 /*---------------------------------------------------------------------------*/
00624 /* Definition of static functions                                            */
00625 /*---------------------------------------------------------------------------*/
00626 
00627 
00637 static mdd_t *
00638 ImageByInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
00639                   mdd_t *from, array_t *relationArray, mdd_t *cofactorCube,
00640                   mdd_t *abstractCube, int splitMethod, int turnDepth,
00641                   int depth)
00642 {
00643   array_t               *newVector, *tmpVector;
00644   mdd_t                 *new_, *resT, *resE, *res, *resPart, *resTmp;
00645   mdd_t                 *var, *varNot, *cube, *tmp, *func;
00646   int                   size, i, j, k, vectorSize;
00647   array_t               *vectorArray, *varArray;
00648   int                   hit, turnFlag;
00649   int                   split, nGroups, cubeSize;
00650   mdd_t                 *refResult, *product;
00651   mdd_t                 *newFrom, *fromT, *fromE;
00652   ImgComponent_t        *comp;
00653   array_t               *relationArrayT, *relationArrayE, *partRelationArray;
00654   int                   constConstrain;
00655   int                   nRecur;
00656   array_t               *newRelationArray, *tmpRelationArray, *abstractVars;
00657   mdd_t                 *cofactor, *abstract;
00658   mdd_t                 *newCofactorCube, *newAbstractCube;
00659   mdd_t                 *partCofactorCube, *partAbstractCube;
00660   mdd_t                 *cofactorCubeT, *cofactorCubeE;
00661   mdd_t                 *abstractCubeT, *abstractCubeE;
00662   mdd_t                 *essentialCube, *tmpRes;
00663   int                   findEssential;
00664   int                   foundEssentialDepth;
00665   int                   foundEssentialDepthT, foundEssentialDepthE;
00666   array_t               *vectorT, *vectorE;
00667   mdd_t                 *andT, *andE, *one;
00668   float                 prevLambda;
00669   int                   prevTotal, prevVectorBddSize, prevVectorSize;
00670   int                   arraySize, nFuncs;
00671 
00672   newRelationArray = NIL(array_t);
00673 
00674   if (info->option->delayedSplit && relationArray) {
00675     ImgVectorConstrain(info, vector, constraint, relationArray,
00676                         &newVector, &res, &newRelationArray,
00677                         &cofactor, &abstract, TRUE);
00678     newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
00679     mdd_free(cofactor);
00680     newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
00681     mdd_free(abstract);
00682     if (info->option->debug) {
00683       refResult = ImgImageByHybrid(info, newVector, from);
00684       resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00685                                                 newRelationArray,
00686                                                 newCofactorCube,
00687                                                 newAbstractCube);
00688       assert(mdd_equal(refResult, resPart));
00689       mdd_free(refResult);
00690       mdd_free(resPart);
00691     }
00692   } else {
00693     ImgVectorConstrain(info, vector, constraint, relationArray,
00694                         &newVector, &res, &newRelationArray,
00695                         NIL(mdd_t *), NIL(mdd_t *), TRUE);
00696     newCofactorCube = NIL(mdd_t);
00697     newAbstractCube = NIL(mdd_t);
00698     if (info->option->debug) {
00699       refResult = ImgImageByHybrid(info, newVector, from);
00700       resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00701                                                 newRelationArray,
00702                                                 NIL(mdd_t), NIL(mdd_t));
00703       assert(mdd_equal(refResult, resPart));
00704       mdd_free(refResult);
00705 
00706       refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00707                                                 relationArray,
00708                                                 NIL(mdd_t), NIL(mdd_t));
00709       resTmp = mdd_and(resPart, res, 1, 1);
00710       mdd_free(resPart);
00711       assert(mdd_equal(refResult, resTmp));
00712       mdd_free(refResult);
00713       mdd_free(resTmp);
00714     }
00715   }
00716 
00717   if (info->option->checkEquivalence &&
00718       relationArray && !info->option->buildPartialTR) {
00719     assert(ImgCheckEquivalence(info, newVector, newRelationArray,
00720                                 newCofactorCube, newAbstractCube, 0));
00721   }
00722 
00723   if (from && info->option->findEssential) {
00724     if (info->option->findEssential == 1)
00725       findEssential = 1;
00726     else {
00727       if (depth >= info->lastFoundEssentialDepth)
00728         findEssential = 1;
00729       else
00730         findEssential = 0;
00731     }
00732   } else
00733     findEssential = 0;
00734   if (findEssential) {
00735     essentialCube = bdd_find_essential_cube(from);
00736 
00737     if (!bdd_is_tautology(essentialCube, 1)) {
00738       info->averageFoundEssential = (info->averageFoundEssential *
00739         (float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
00740         (float)(info->nFoundEssentials + 1);
00741       info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
00742         (float)info->nFoundEssentials + (float)depth) /
00743         (float)(info->nFoundEssentials + 1);
00744       if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
00745         info->topFoundEssentialDepth = depth;
00746       info->nFoundEssentials++;
00747       if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
00748         info->foundEssentials[depth]++;
00749       tmpVector = newVector;
00750       tmpRelationArray = newRelationArray;
00751       if (info->option->delayedSplit && relationArray) {
00752         ImgVectorMinimize(info, tmpVector, essentialCube, NIL(mdd_t),
00753                           tmpRelationArray, &newVector, &tmpRes,
00754                           &newRelationArray, &cofactor, &abstract);
00755         tmp = newCofactorCube;
00756         newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
00757         mdd_free(tmp);
00758         mdd_free(cofactor);
00759         tmp = newAbstractCube;
00760         newAbstractCube = mdd_and(tmp, abstract, 1, 1);
00761         mdd_free(tmp);
00762         mdd_free(abstract);
00763       } else {
00764         ImgVectorMinimize(info, tmpVector, essentialCube, NIL(mdd_t),
00765                           tmpRelationArray, &newVector, &tmpRes,
00766                           &newRelationArray, NIL(mdd_t *), NIL(mdd_t *));
00767       }
00768       tmp = res;
00769       res = mdd_and(tmp, tmpRes, 1, 1);
00770       mdd_free(tmp);
00771       ImgVectorFree(tmpVector);
00772       if (tmpRelationArray && tmpRelationArray != relationArray &&
00773           tmpRelationArray != newRelationArray)
00774         mdd_array_free(tmpRelationArray);
00775       foundEssentialDepth = depth;
00776     } else
00777       foundEssentialDepth = info->option->maxEssentialDepth;
00778     mdd_free(essentialCube);
00779     foundEssentialDepthT = info->option->maxEssentialDepth;
00780     foundEssentialDepthE = info->option->maxEssentialDepth;
00781   } else {
00782     /* To remove compiler warnings */
00783     foundEssentialDepth = -1;
00784     foundEssentialDepthT = -1;
00785     foundEssentialDepthE = -1;
00786   }
00787 
00788   if (info->option->debug) {
00789     if (relationArray && from) {
00790       refResult = ImgImageByHybrid(info, newVector, from);
00791       resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00792                                                 newRelationArray,
00793                                                 newCofactorCube,
00794                                                 newAbstractCube);
00795       assert(mdd_equal(refResult, resPart));
00796       mdd_free(refResult);
00797       mdd_free(resPart);
00798     }
00799   }
00800 
00801   info->nRecursion++;
00802   arraySize = array_n(newVector);
00803   if (info->nIntermediateVars)
00804     nFuncs = ImgVectorFunctionSize(newVector);
00805   else
00806     nFuncs = arraySize;
00807   if (nFuncs <= 1) {
00808     if (info->useConstraint) {
00809       if (nFuncs == 1) {
00810         comp = array_fetch(ImgComponent_t *, newVector, 0);
00811         if (arraySize > 1)
00812           func = ImgGetComposedFunction(newVector);
00813         else
00814           func = comp->func;
00815         if (mdd_lequal(from, func, 1, 1)) { /* func | from = 1 */
00816           tmp = res;
00817           res = mdd_and(tmp, comp->var, 1, 1);
00818           mdd_free(tmp);
00819         } else if (mdd_lequal(func, from, 1, 0)) { /* func | from = 0 */
00820           tmp = res;
00821           res = mdd_and(tmp, comp->var, 1, 0);
00822           mdd_free(tmp);
00823         }
00824         if (arraySize > 1)
00825           mdd_free(func);
00826       }
00827     }
00828     if (relationArray && newRelationArray != relationArray)
00829       mdd_array_free(newRelationArray);
00830     if (newCofactorCube)
00831       mdd_free(newCofactorCube);
00832     if (newAbstractCube)
00833       mdd_free(newAbstractCube);
00834     ImgVectorFree(newVector);
00835     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
00836                           (float)depth) / (float)(info->nLeaves + 1);
00837     if (depth > info->maxDepth)
00838       info->maxDepth = depth;
00839     info->nLeaves++;
00840     if (findEssential)
00841       info->foundEssentialDepth = foundEssentialDepth;
00842     if (info->option->debug)
00843       assert(TfmCheckImageValidity(info, res));
00844     return(res);
00845   }
00846 
00847   turnFlag = 0;
00848   if (splitMethod == 3 && turnDepth == -1) {
00849     if (depth < info->option->splitMinDepth) {
00850       info->nSplits++;
00851       turnFlag = 0;
00852     } else if (depth > info->option->splitMaxDepth) {
00853       info->nConjoins++;
00854       turnFlag = 1;
00855     } else {
00856       turnFlag = ImgDecideSplitOrConjoin(info, newVector, from, 0,
00857                                          newRelationArray, newCofactorCube,
00858                                          newAbstractCube, 0, depth);
00859     }
00860   } else {
00861     if (splitMethod != 0) {
00862       if (depth == turnDepth)
00863         turnFlag = 1;
00864     }
00865   }
00866   if (turnFlag || nFuncs == 2) {
00867     hit = 1;
00868     if (!info->imgCache ||
00869         !(resPart = ImgCacheLookupTable(info, info->imgCache, newVector,
00870                                         from))) {
00871       hit = 0;
00872       if (nFuncs == 2) {
00873         if (info->useConstraint) {
00874           ImgVectorConstrain(info, newVector, from, NIL(array_t),
00875                              &tmpVector, &resTmp, NIL(array_t *),
00876                              NIL(mdd_t *), NIL(mdd_t *), FALSE);
00877           if (array_n(tmpVector) <= 1)
00878             resPart = resTmp;
00879           else {
00880             mdd_free(resTmp);
00881             resPart = ImageFast2(info, tmpVector);
00882           }
00883           ImgVectorFree(tmpVector);
00884         } else
00885           resPart = ImageFast2(info, newVector);
00886       } else if (splitMethod == 2) {
00887         if (info->useConstraint) {
00888           ImgVectorConstrain(info, newVector, from, NIL(array_t),
00889                              &tmpVector, &resTmp, NIL(array_t *),
00890                              NIL(mdd_t *), NIL(mdd_t *), FALSE);
00891           if (array_n(tmpVector) <= 1)
00892             resPart = resTmp;
00893           else if (array_n(tmpVector) == 2) {
00894             mdd_free(resTmp);
00895             resPart = ImageFast2(info, tmpVector);
00896           } else {
00897             tmp = mdd_one(info->manager);
00898             resPart = ImageByOutputSplit(info, tmpVector, tmp, depth + 1);
00899             mdd_free(tmp);
00900             tmp = resPart;
00901             resPart = mdd_and(tmp, resTmp, 1, 1);
00902             mdd_free(tmp);
00903             mdd_free(resTmp);
00904           }
00905           ImgVectorFree(tmpVector);
00906         } else {
00907           tmp = mdd_one(info->manager);
00908           resPart = ImageByOutputSplit(info, newVector, tmp, depth + 1);
00909           mdd_free(tmp);
00910         }
00911       } else {
00912         if (relationArray) {
00913           resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
00914                                                     newRelationArray,
00915                                                     newCofactorCube,
00916                                                     newAbstractCube);
00917         } else
00918           resPart = ImgImageByHybrid(info, newVector, from);
00919       }
00920       if (info->imgCache) {
00921         if (from) {
00922           ImgCacheInsertTable(info->imgCache, newVector, mdd_dup(from),
00923                                 resPart);
00924         } else
00925           ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t), resPart);
00926       }
00927     }
00928 
00929     if (relationArray && newRelationArray != relationArray)
00930       mdd_array_free(newRelationArray);
00931     if (newCofactorCube)
00932       mdd_free(newCofactorCube);
00933     if (newAbstractCube)
00934       mdd_free(newAbstractCube);
00935 
00936     if (info->option->debug) {
00937       refResult = ImgImageByHybrid(info, newVector, from);
00938       assert(mdd_equal(refResult, resPart));
00939       mdd_free(refResult);
00940     }
00941 
00942     new_ = mdd_and(res, resPart, 1, 1);
00943     if (info->option->verbosity) {
00944       size = bdd_size(new_);
00945       if (size > info->maxIntermediateSize)
00946         info->maxIntermediateSize = size;
00947       if (info->option->printBddSize) {
00948         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
00949                 bdd_size(res), bdd_size(resPart), size);
00950       }
00951     }
00952     mdd_free(res);
00953     res = new_;
00954     if (!info->imgCache || hit) {
00955       mdd_free(resPart);
00956       ImgVectorFree(newVector);
00957     }
00958     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
00959                           (float)depth) / (float)(info->nLeaves + 1);
00960     if (depth > info->maxDepth)
00961       info->maxDepth = depth;
00962     info->nLeaves++;
00963     if (turnFlag)
00964       info->nTurns++;
00965     if (findEssential)
00966       info->foundEssentialDepth = foundEssentialDepth;
00967     if (info->option->debug)
00968       assert(TfmCheckImageValidity(info, res));
00969     return(res);
00970   }
00971 
00972   if (info->imgCache) {
00973     resPart = ImgCacheLookupTable(info, info->imgCache, newVector, from);
00974     if (resPart) {
00975       if (info->option->debug) {
00976         refResult = ImgImageByHybrid(info, newVector, from);
00977         assert(mdd_equal(refResult, resPart));
00978         mdd_free(refResult);
00979       }
00980       new_ = mdd_and(res, resPart, 1, 1);
00981       if (info->option->verbosity) {
00982         size = bdd_size(new_);
00983         if (size > info->maxIntermediateSize)
00984           info->maxIntermediateSize = size;
00985         if (info->option->printBddSize) {
00986           fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
00987                   bdd_size(res), bdd_size(resPart), size);
00988         }
00989       }
00990       mdd_free(res);
00991       mdd_free(resPart);
00992       res = new_;
00993       ImgVectorFree(newVector);
00994       if (relationArray && newRelationArray != relationArray)
00995         mdd_array_free(newRelationArray);
00996       if (newCofactorCube)
00997         mdd_free(newCofactorCube);
00998       if (newAbstractCube)
00999         mdd_free(newAbstractCube);
01000       if (findEssential)
01001         info->foundEssentialDepth = foundEssentialDepth;
01002       if (info->option->debug)
01003         assert(TfmCheckImageValidity(info, res));
01004       return(res);
01005     }
01006   }
01007 
01008   if (info->option->splitCubeFunc) {
01009     split = -1;
01010     cubeSize = 0;
01011     for (i = 0; i < array_n(newVector); i++) {
01012       comp = array_fetch(ImgComponent_t *, newVector, i);
01013       if (bdd_is_cube(comp->func)) {
01014         if (split == -1 || info->option->splitCubeFunc == 1 ||
01015             bdd_size(comp->func) > cubeSize) {
01016           split = i;
01017           cubeSize = bdd_size(comp->func);
01018           break;
01019         }
01020       }
01021     }
01022     if (split != -1) {
01023       comp = array_fetch(ImgComponent_t *, newVector, split);
01024       info->nCubeSplits++;
01025       if (info->option->delayedSplit && relationArray) {
01026         ImgVectorConstrain(info, newVector, comp->func, newRelationArray,
01027                            &vectorT, &andT, &relationArrayT,
01028                            &cofactor, &abstract, FALSE);
01029         cofactorCubeT = mdd_and(newCofactorCube, cofactor, 1, 1);
01030         mdd_free(cofactor);
01031         abstractCubeT = mdd_and(newAbstractCube, abstract, 1, 1);
01032         mdd_free(abstract);
01033       } else {
01034         ImgVectorConstrain(info, newVector, comp->func, newRelationArray,
01035                            &vectorT, &andT, &relationArrayT,
01036                            NIL(mdd_t *), NIL(mdd_t *), FALSE);
01037         cofactorCubeT = NIL(mdd_t);
01038         abstractCubeT = NIL(mdd_t);
01039       }
01040       if (from)
01041         newFrom = bdd_cofactor(from, comp->func);
01042       else
01043         newFrom = from;
01044       if (info->option->checkEquivalence &&
01045           relationArray && !info->option->buildPartialTR) {
01046         assert(ImgCheckEquivalence(info, vectorT, relationArrayT,
01047                                    cofactorCubeT, abstractCubeT, 0));
01048       }
01049 
01050       one = mdd_one(info->manager);
01051       if (newFrom && bdd_is_tautology(newFrom, 0))
01052         resT = mdd_zero(info->manager);
01053       else {
01054         prevLambda = info->prevLambda;
01055         prevTotal = info->prevTotal;
01056         prevVectorBddSize = info->prevVectorBddSize;
01057         prevVectorSize = info->prevVectorSize;
01058         resT = ImageByInputSplit(info, vectorT, one, newFrom,
01059                               relationArrayT, cofactorCubeT, abstractCubeT,
01060                               splitMethod, turnDepth, depth + 1);
01061         info->prevLambda = prevLambda;
01062         info->prevTotal = prevTotal;
01063         info->prevVectorBddSize = prevVectorBddSize;
01064         info->prevVectorSize = prevVectorSize;
01065       }
01066       ImgVectorFree(vectorT);
01067       if (newFrom)
01068         mdd_free(newFrom);
01069       if (!bdd_is_tautology(andT, 1)) {
01070         tmp = resT;
01071         resT = mdd_and(tmp, andT, 1, 1);
01072         mdd_free(tmp);
01073       }
01074       if (findEssential)
01075         foundEssentialDepthT = info->foundEssentialDepth;
01076       if (relationArrayT && relationArrayT != newRelationArray)
01077         mdd_array_free(relationArrayT);
01078       if (cofactorCubeT && cofactorCubeT != newCofactorCube)
01079         mdd_free(cofactorCubeT);
01080       if (abstractCubeT && abstractCubeT != newAbstractCube)
01081         mdd_free(abstractCubeT);
01082 
01083       tmp = mdd_not(comp->func);
01084       if (info->option->delayedSplit && relationArray) {
01085         ImgVectorConstrain(info, newVector, tmp, newRelationArray,
01086                            &vectorE, &andE, &relationArrayE,
01087                            &cofactor, &abstract, FALSE);
01088         cofactorCubeE = mdd_and(newCofactorCube, cofactor, 1, 1);
01089         mdd_free(cofactor);
01090         abstractCubeE = mdd_and(newAbstractCube, abstract, 1, 1);
01091         mdd_free(abstract);
01092       } else {
01093         ImgVectorConstrain(info, newVector, tmp, newRelationArray,
01094                            &vectorE, &andE, &relationArrayE,
01095                            NIL(mdd_t *), NIL(mdd_t *), FALSE);
01096         cofactorCubeE = NIL(mdd_t);
01097         abstractCubeE = NIL(mdd_t);
01098       }
01099       if (from)
01100         newFrom = bdd_cofactor(from, tmp);
01101       else
01102         newFrom = from;
01103       mdd_free(tmp);
01104       if (relationArray && newRelationArray != relationArray)
01105         mdd_array_free(newRelationArray);
01106       if (newCofactorCube)
01107         mdd_free(newCofactorCube);
01108       if (newAbstractCube)
01109         mdd_free(newAbstractCube);
01110       if (info->option->checkEquivalence &&
01111           relationArray && !info->option->buildPartialTR) {
01112         assert(ImgCheckEquivalence(info, vectorE, relationArrayE,
01113                                    cofactorCubeE, abstractCubeE, 0));
01114       }
01115 
01116       if (newFrom && bdd_is_tautology(newFrom, 0))
01117         resE = mdd_zero(info->manager);
01118       else {
01119         resE = ImageByInputSplit(info, vectorE, one, newFrom,
01120                               relationArrayE, cofactorCubeE, abstractCubeE,
01121                               splitMethod, turnDepth, depth + 1);
01122       }
01123       ImgVectorFree(vectorE);
01124       if (newFrom)
01125         mdd_free(newFrom);
01126       if (!bdd_is_tautology(andE, 1)) {
01127         tmp = resE;
01128         resE = mdd_and(tmp, andE, 1, 1);
01129         mdd_free(tmp);
01130       }
01131       if (findEssential)
01132         foundEssentialDepthE = info->foundEssentialDepth;
01133       if (relationArrayE && relationArrayE != newRelationArray)
01134         mdd_array_free(relationArrayE);
01135       if (cofactorCubeE && cofactorCubeE != newCofactorCube)
01136         mdd_free(cofactorCubeE);
01137       if (abstractCubeE && abstractCubeE != newAbstractCube)
01138         mdd_free(abstractCubeE);
01139 
01140       resPart = bdd_ite(comp->var, resT, resE, 1, 1, 1);
01141       if (info->option->verbosity) {
01142         size = bdd_size(resPart);
01143         if (size > info->maxIntermediateSize)
01144           info->maxIntermediateSize = size;
01145         if (info->option->printBddSize) {
01146           fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
01147                   bdd_size(resT), bdd_size(resE), size);
01148         }
01149       }
01150       mdd_free(one);
01151 
01152       if (info->imgCache)
01153         ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t), resPart);
01154 
01155       if (info->option->debug) {
01156         refResult = ImgImageByHybrid(info, newVector, from);
01157         assert(mdd_equal(refResult, resPart));
01158         mdd_free(refResult);
01159       }
01160 
01161       new_ = mdd_and(res, resPart, 1, 1);
01162       if (info->option->verbosity) {
01163         size = bdd_size(new_);
01164         if (size > info->maxIntermediateSize)
01165           info->maxIntermediateSize = size;
01166         if (info->option->printBddSize) {
01167           fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
01168                   bdd_size(res), bdd_size(resPart), size);
01169         }
01170       }
01171       mdd_free(res);
01172       res = new_;
01173 
01174       if (info->option->debug) {
01175         refResult = ImgImageByHybrid(info, newVector, from);
01176         assert(mdd_equal(refResult, resPart));
01177         mdd_free(refResult);
01178       }
01179 
01180       if (!info->imgCache) {
01181         mdd_free(resPart);
01182         ImgVectorFree(newVector);
01183       }
01184       info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01185                             (float)depth) / (float)(info->nLeaves + 1);
01186       if (depth > info->maxDepth)
01187         info->maxDepth = depth;
01188       info->nLeaves++;
01189       if (turnFlag)
01190         info->nTurns++;
01191       if (findEssential) {
01192         if (foundEssentialDepth == info->option->maxEssentialDepth) {
01193           if (foundEssentialDepthT < foundEssentialDepthE)
01194             foundEssentialDepth = foundEssentialDepthT;
01195           else
01196             foundEssentialDepth = foundEssentialDepthE;
01197         }
01198         info->foundEssentialDepth = foundEssentialDepth;
01199       }
01200       if (info->option->debug)
01201         assert(TfmCheckImageValidity(info, res));
01202       return(res);
01203     }
01204   }
01205 
01206   /* compute disconnected component and best variable selection */
01207   vectorArray = array_alloc(array_t *, 0);
01208   varArray = array_alloc(int, 0);
01209   if (info->option->delayedSplit && relationArray) {
01210     nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, from, 0,
01211                                         info->option->inputSplit,
01212                                         info->option->piSplitFlag,
01213                                         vectorArray, varArray, &product,
01214                                         newRelationArray, &tmpRelationArray,
01215                                         &cofactor, &abstract);
01216   } else {
01217     nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, from, 0,
01218                                         info->option->inputSplit,
01219                                         info->option->piSplitFlag,
01220                                         vectorArray, varArray, &product,
01221                                         newRelationArray, &tmpRelationArray,
01222                                         NIL(mdd_t *), NIL(mdd_t *));
01223     cofactor = NIL(mdd_t);
01224     abstract = NIL(mdd_t);
01225 
01226     if (info->option->debug && nGroups >= 1) {
01227       if (info->option->verbosity > 1) {
01228         ImgPrintVectorDependency(info, newVector, info->option->verbosity);
01229         PrintVectorDecomposition(info, vectorArray, varArray);
01230       }
01231 
01232       refResult = ImgImageByHybrid(info, newVector, from);
01233       resPart = mdd_dup(product);
01234       for (i = 0; i < array_n(vectorArray); i++) {
01235         vector = array_fetch(array_t *, vectorArray, i);
01236         resTmp = ImgImageByHybrid(info, vector, from);
01237         tmp = resPart;
01238         resPart = mdd_and(tmp, resTmp, 1, 1);
01239         mdd_free(tmp);
01240         mdd_free(resTmp);
01241 
01242         if (arraySize > nFuncs) {
01243           split = array_fetch(int, varArray, i);
01244           assert(!st_is_member(info->intermediateVarsTable,
01245                  (char *)(long)split));
01246         }
01247       }
01248       assert(mdd_equal(refResult, resPart));
01249       mdd_free(refResult);
01250       mdd_free(resPart);
01251     }
01252   }
01253   vectorSize = array_n(newVector);
01254   if ((!info->imgCache || nGroups <= 1) && !info->option->debug)
01255     ImgVectorFree(newVector);
01256   if (newRelationArray) {
01257     if (newRelationArray != relationArray &&
01258         tmpRelationArray != newRelationArray) {
01259       mdd_array_free(newRelationArray);
01260     }
01261     newRelationArray = tmpRelationArray;
01262   }
01263   if (nGroups == 0) {
01264     if (relationArray && newRelationArray != relationArray)
01265       mdd_array_free(newRelationArray);
01266     if (newCofactorCube)
01267       mdd_free(newCofactorCube);
01268     if (newAbstractCube)
01269       mdd_free(newAbstractCube);
01270     if (cofactor)
01271       mdd_free(cofactor);
01272     if (abstract)
01273       mdd_free(abstract);
01274 
01275     array_free(vectorArray);
01276     array_free(varArray);
01277 
01278     if (info->option->debug) {
01279       refResult = ImgImageByHybrid(info, newVector, from);
01280       assert(mdd_equal(refResult, product));
01281       mdd_free(refResult);
01282       ImgVectorFree(newVector);
01283     }
01284 
01285     new_ = mdd_and(res, product, 1, 1);
01286     if (info->option->verbosity) {
01287       size = bdd_size(new_);
01288       if (size > info->maxIntermediateSize)
01289         info->maxIntermediateSize = size;
01290       if (info->option->printBddSize) {
01291         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
01292                 bdd_size(res), bdd_size(product), size);
01293       }
01294     }
01295     mdd_free(res);
01296     mdd_free(product);
01297     res = new_;
01298 
01299     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01300                           (float)depth) / (float)(info->nLeaves + 1);
01301     if (depth > info->maxDepth)
01302       info->maxDepth = depth;
01303     info->nLeaves++;
01304     if (findEssential)
01305       info->foundEssentialDepth = foundEssentialDepth;
01306     if (info->option->debug)
01307       assert(TfmCheckImageValidity(info, res));
01308     return(res);
01309   }
01310 
01311   if (info->option->delayedSplit && relationArray) {
01312     tmp = newCofactorCube;
01313     newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
01314     mdd_free(tmp);
01315     mdd_free(cofactor);
01316     tmp = newAbstractCube;
01317     newAbstractCube = mdd_and(tmp, abstract, 1, 1);
01318     mdd_free(tmp);
01319     mdd_free(abstract);
01320   }
01321 
01322   if (nGroups > 1) {
01323     if (info->nDecomps == 0 || depth < info->topDecomp)
01324       info->topDecomp = depth;
01325     if (info->nDecomps == 0 || vectorSize > info->maxDecomp)
01326       info->maxDecomp = vectorSize;
01327     info->averageDecomp = (info->averageDecomp * (float)info->nDecomps +
01328                           (float)nGroups) / (float)(info->nDecomps + 1);
01329     info->nDecomps++;
01330   }
01331 
01332   if (relationArray && nGroups > 1) {
01333     abstractVars = array_alloc(mdd_t *, 0);
01334     for (i = 0; i < array_n(vectorArray); i++) {
01335       vector = array_fetch(array_t *, vectorArray, i);
01336       cube = mdd_one(info->manager);
01337       for (j = 0; j < nGroups; j++) {
01338         if (j == i)
01339           continue;
01340         tmpVector = array_fetch(array_t *, vectorArray, j);
01341         for (k = 0; k < array_n(tmpVector); k++) {
01342           comp = array_fetch(ImgComponent_t *, tmpVector, k);
01343           tmp = cube;
01344           cube = mdd_and(cube, comp->var, 1, 1);
01345           mdd_free(tmp);
01346         }
01347       }
01348       tmp = ImgSubstitute(cube, info->functionData, Img_D2R_c);
01349       mdd_free(cube);
01350       array_insert_last(mdd_t *, abstractVars, tmp);
01351     }
01352   } else
01353     abstractVars = NIL(array_t);
01354   for (i = 0; i < array_n(vectorArray); i++) {
01355     vector = array_fetch(array_t *, vectorArray, i);
01356     if (from)
01357       newFrom = mdd_dup(from);
01358     else
01359       newFrom = from;
01360 
01361     if (relationArray) {
01362       if (nGroups == 1) {
01363         partRelationArray = newRelationArray;
01364         if (info->option->delayedSplit) {
01365           partCofactorCube = newCofactorCube;
01366           partAbstractCube = newAbstractCube;
01367         } else {
01368           partCofactorCube = NIL(mdd_t);
01369           partAbstractCube = NIL(mdd_t);
01370         }
01371       } else {
01372         cube = array_fetch(mdd_t *, abstractVars, i);
01373         if (info->option->delayedSplit) {
01374           partRelationArray = newRelationArray;
01375           partCofactorCube = mdd_dup(newCofactorCube);
01376           partAbstractCube = mdd_and(newAbstractCube, cube, 1, 1);
01377         } else {
01378           partRelationArray = ImgGetAbstractedRelationArray(info->manager,
01379                                                             newRelationArray,
01380                                                             cube);
01381           mdd_free(cube);
01382           partCofactorCube = NIL(mdd_t);
01383           partAbstractCube = NIL(mdd_t);
01384         }
01385       }
01386       if (info->option->debug) {
01387         refResult = ImgImageByHybrid(info, vector, from);
01388         resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
01389                                                   partRelationArray,
01390                                                   partCofactorCube,
01391                                                   partAbstractCube);
01392         assert(mdd_equal(refResult, resPart));
01393         mdd_free(refResult);
01394         mdd_free(resPart);
01395       }
01396     } else {
01397       partRelationArray = newRelationArray;
01398       partCofactorCube = NIL(mdd_t);
01399       partAbstractCube = NIL(mdd_t);
01400     }
01401     hit = 1;
01402     if (!info->imgCache || nGroups == 1 ||
01403         !(resPart = ImgCacheLookupTable(info, info->imgCache, vector,
01404                                         newFrom))) {
01405       hit = 0;
01406       if (arraySize > nFuncs)
01407         size = ImgVectorFunctionSize(vector);
01408       else
01409         size = array_n(vector);
01410       if (size == 1) {
01411         comp = array_fetch(ImgComponent_t *, vector, 0);
01412         if (array_n(vector) > 1)
01413           func = ImgGetComposedFunction(vector);
01414         else
01415           func = comp->func;
01416         if (info->useConstraint) {
01417           constConstrain = ImgConstConstrain(func, newFrom);
01418           if (constConstrain == 1)
01419             resPart = mdd_dup(comp->var);
01420           else if (constConstrain == 0)
01421             resPart = mdd_not(comp->var);
01422           else
01423             resPart = mdd_one(info->manager);
01424         } else {
01425           if (bdd_is_tautology(func, 1))
01426             resPart = mdd_dup(comp->var);
01427           else if (bdd_is_tautology(func, 0))
01428             resPart = mdd_not(comp->var);
01429           else
01430             resPart = mdd_one(info->manager);
01431         }
01432         if (array_n(vector) > 1)
01433           mdd_free(func);
01434         info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01435                                 (float)depth) / (float)(info->nLeaves + 1);
01436         if (depth > info->maxDepth)
01437           info->maxDepth = depth;
01438         info->nLeaves++;
01439       } else if (size == 2) {
01440         if (info->useConstraint) {
01441           ImgVectorConstrain(info, vector, newFrom, NIL(array_t),
01442                              &newVector, &resTmp, NIL(array_t *),
01443                              NIL(mdd_t *), NIL(mdd_t *), FALSE);
01444           if (array_n(newVector) <= 1)
01445             resPart = resTmp;
01446           else {
01447             mdd_free(resTmp);
01448             resPart = ImageFast2(info, newVector);
01449           }
01450           ImgVectorFree(newVector);
01451         } else
01452           resPart = ImageFast2(info, vector);
01453         info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01454                                 (float)depth) / (float)(info->nLeaves + 1);
01455         if (depth > info->maxDepth)
01456           info->maxDepth = depth;
01457         info->nLeaves++;
01458       } else {
01459         nRecur = 0;
01460         split = array_fetch(int, varArray, i);
01461         if (partRelationArray && info->imgKeepPiInTr == FALSE) {
01462           if (st_lookup(info->quantifyVarsTable, (char *)(long)split,
01463                         NIL(char *))) {
01464             int newSplit;
01465 
01466             /* checks the splitting is valid */
01467             newSplit = CheckIfValidSplitOrGetNew(info, split, vector,
01468                                                 partRelationArray, from);
01469             if (newSplit == -1) {
01470               resPart = ImgImageByHybrid(info, vector, from);
01471               info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01472                                 (float)depth) / (float)(info->nLeaves + 1);
01473               if (depth > info->maxDepth)
01474                 info->maxDepth = depth;
01475               info->nLeaves++;
01476               info->nTurns++;
01477               goto cache;
01478             }
01479             split = newSplit;
01480           }
01481         }
01482         var = bdd_var_with_index(info->manager, split);
01483         if (newFrom)
01484           fromT = bdd_cofactor(newFrom, var);
01485         else
01486           fromT = NIL(mdd_t);
01487         if (partRelationArray) {
01488           if (info->option->delayedSplit) {
01489             relationArrayT = partRelationArray;
01490             cofactorCubeT = mdd_and(partCofactorCube, var, 1, 1);
01491           } else {
01492             relationArrayT = ImgGetCofactoredRelationArray(partRelationArray,
01493                                                            var);
01494             cofactorCubeT = partCofactorCube;
01495           }
01496         } else {
01497           relationArrayT = NIL(array_t);
01498           cofactorCubeT = NIL(mdd_t);
01499         }
01500         if (!fromT || !bdd_is_tautology(fromT, 0)) {
01501           prevLambda = info->prevLambda;
01502           prevTotal = info->prevTotal;
01503           prevVectorBddSize = info->prevVectorBddSize;
01504           prevVectorSize = info->prevVectorSize;
01505           resT = ImageByInputSplit(info, vector, var, fromT,
01506                                 relationArrayT, cofactorCubeT, partAbstractCube,
01507                                 splitMethod, turnDepth, depth + 1);
01508           if (info->option->debug) {
01509             refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
01510                                                         fromT, relationArrayT,
01511                                                         cofactorCubeT,
01512                                                         partAbstractCube);
01513             assert(mdd_equal(refResult, resT));
01514             mdd_free(refResult);
01515           }
01516           info->prevLambda = prevLambda;
01517           info->prevTotal = prevTotal;
01518           info->prevVectorBddSize = prevVectorBddSize;
01519           info->prevVectorSize = prevVectorSize;
01520           if (findEssential)
01521             foundEssentialDepthT = info->foundEssentialDepth;
01522           nRecur++;
01523         } else
01524           resT = mdd_zero(info->manager);
01525         if (fromT)
01526           mdd_free(fromT);
01527         if (relationArrayT && relationArrayT != partRelationArray)
01528           mdd_array_free(relationArrayT);
01529         if (cofactorCubeT && cofactorCubeT != partCofactorCube)
01530           mdd_free(cofactorCubeT);
01531 
01532         if (bdd_is_tautology(resT, 1)) {
01533           mdd_free(var);
01534           resPart = resT;
01535           info->nEmptySubImage++;
01536         } else {
01537           varNot = mdd_not(var);
01538           mdd_free(var);
01539           if (newFrom)
01540             fromE = bdd_cofactor(newFrom, varNot);
01541           else
01542             fromE = NIL(mdd_t);
01543           if (partRelationArray) {
01544             if (info->option->delayedSplit) {
01545               relationArrayE = partRelationArray;
01546               cofactorCubeE = mdd_and(partCofactorCube, varNot, 1, 1);
01547             } else {
01548               relationArrayE = ImgGetCofactoredRelationArray(partRelationArray,
01549                                                              varNot);
01550               cofactorCubeE = partCofactorCube;
01551             }
01552           } else {
01553             relationArrayE = NIL(array_t);
01554             cofactorCubeE = NIL(mdd_t);
01555           }
01556           if (!fromE || !bdd_is_tautology(fromE, 0)) {
01557             resE = ImageByInputSplit(info, vector, varNot, fromE,
01558                           relationArrayE, cofactorCubeE, partAbstractCube,
01559                           splitMethod, turnDepth, depth + 1);
01560             if (info->option->debug) {
01561               refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
01562                                                           fromE, relationArrayE,
01563                                                           cofactorCubeE,
01564                                                           partAbstractCube);
01565               assert(mdd_equal(refResult, resE));
01566               mdd_free(refResult);
01567             }
01568             if (findEssential)
01569               foundEssentialDepthE = info->foundEssentialDepth;
01570             nRecur++;
01571           } else
01572             resE = mdd_zero(info->manager);
01573           mdd_free(varNot);
01574           if (fromE)
01575             mdd_free(fromE);
01576           if (relationArrayE && relationArrayE != partRelationArray)
01577             mdd_array_free(relationArrayE);
01578           if (cofactorCubeE && cofactorCubeE != partCofactorCube)
01579             mdd_free(cofactorCubeE);
01580     
01581           resPart = mdd_or(resT, resE, 1, 1);
01582           if (info->option->debug) {
01583             refResult = ImgImageByHybrid(info, vector, from);
01584             assert(mdd_equal(refResult, resPart));
01585             mdd_free(refResult);
01586           }
01587           if (info->option->verbosity) {
01588             size = bdd_size(resPart);
01589             if (size > info->maxIntermediateSize)
01590               info->maxIntermediateSize = size;
01591             if (info->option->printBddSize) {
01592               fprintf(vis_stdout, "** tfm info: bdd_or(%d,%d) = %d\n",
01593                       bdd_size(resT), bdd_size(resE), size);
01594             }
01595           }
01596 
01597           mdd_free(resT);
01598           mdd_free(resE);
01599         }
01600         if (nRecur == 0) {
01601           info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01602                                 (float)depth) / (float)(info->nLeaves + 1);
01603           if (depth > info->maxDepth)
01604             info->maxDepth = depth;
01605           info->nLeaves++;
01606         }
01607       }
01608 cache:
01609       if (info->imgCache) {
01610         ImgCacheInsertTable(info->imgCache, vector, newFrom, resPart);
01611         if (info->option->debug) {
01612           refResult = ImgImageByHybrid(info, vector, newFrom);
01613           assert(mdd_equal(refResult, resPart));
01614           mdd_free(refResult);
01615         }
01616       }
01617     }
01618     if (!info->imgCache || hit) {
01619       ImgVectorFree(vector);
01620       if (newFrom)
01621         mdd_free(newFrom);
01622     }
01623     new_ = mdd_and(product, resPart, 1, 1);
01624     if (info->option->verbosity) {
01625       size = bdd_size(new_);
01626       if (size > info->maxIntermediateSize)
01627         info->maxIntermediateSize = size;
01628       if (info->option->printBddSize) {
01629         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
01630                 bdd_size(product), bdd_size(resPart), size);
01631       }
01632     }
01633     mdd_free(product);
01634     if (!info->imgCache || hit)
01635       mdd_free(resPart);
01636     product = new_;
01637     if (nGroups > 1 && partRelationArray != newRelationArray)
01638       mdd_array_free(partRelationArray);
01639     if (partCofactorCube && partCofactorCube != newCofactorCube)
01640       mdd_free(partCofactorCube);
01641     if (partAbstractCube && partAbstractCube != newAbstractCube)
01642       mdd_free(partAbstractCube);
01643   }
01644   if (abstractVars)
01645     array_free(abstractVars);
01646 
01647   if (relationArray && newRelationArray != relationArray)
01648     mdd_array_free(newRelationArray);
01649   if (newCofactorCube)
01650     mdd_free(newCofactorCube);
01651   if (newAbstractCube)
01652     mdd_free(newAbstractCube);
01653 
01654   array_free(vectorArray);
01655   array_free(varArray);
01656 
01657   if (info->imgCache && nGroups > 1) {
01658     if (from) {
01659       ImgCacheInsertTable(info->imgCache, newVector, mdd_dup(from),
01660                           mdd_dup(product));
01661     } else {
01662       ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t),
01663                           mdd_dup(product));
01664     }
01665   }
01666 
01667   if (info->option->debug) {
01668     refResult = ImgImageByHybrid(info, newVector, from);
01669     assert(mdd_equal(refResult, product));
01670     mdd_free(refResult);
01671     if (!info->imgCache || nGroups == 1)
01672       ImgVectorFree(newVector);
01673   }
01674 
01675   new_ = mdd_and(res, product, 1, 1);
01676   if (info->option->verbosity) {
01677     size = bdd_size(new_);
01678     if (size > info->maxIntermediateSize)
01679       info->maxIntermediateSize = size;
01680     if (info->option->printBddSize) {
01681       fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
01682               bdd_size(res), bdd_size(product), size);
01683     }
01684   }
01685   mdd_free(res);
01686   mdd_free(product);
01687   res = new_;
01688 
01689   if (findEssential) {
01690     if (foundEssentialDepth == info->option->maxEssentialDepth) {
01691       if (foundEssentialDepthT < foundEssentialDepthE)
01692         foundEssentialDepth = foundEssentialDepthT;
01693       else
01694         foundEssentialDepth = foundEssentialDepthE;
01695     }
01696     info->foundEssentialDepth = foundEssentialDepth;
01697   }
01698   if (info->option->debug)
01699     assert(TfmCheckImageValidity(info, res));
01700   return(res);
01701 }
01702 
01703 
01713 static mdd_t *
01714 ImageByStaticInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
01715                         array_t *relationArray, int turnDepth, int depth)
01716 {
01717   array_t       *vectorT, *vectorE, *tmpVector;
01718   mdd_t         *resT, *resE, *res, *tmp, *cubeT, *cubeE;
01719   mdd_t         *fromT, *fromE;
01720   mdd_t         *var, *varNot;
01721   array_t       *relationArrayT, *relationArrayE;
01722   array_t       *newRelationArray, *tmpRelationArray;
01723   int           nRecur;
01724   mdd_t         *refResult, *and_;
01725   mdd_t         *essentialCube;
01726   int           findEssential;
01727   int           foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
01728   int           turnFlag, size;
01729 
01730   info->nRecursion++;
01731 
01732   turnFlag = 0;
01733   if (turnDepth == -1) {
01734     if (depth < info->option->splitMinDepth) {
01735       info->nSplits++;
01736       turnFlag = 0;
01737     } else if (depth > info->option->splitMaxDepth) {
01738       info->nConjoins++;
01739       turnFlag = 1;
01740     } else {
01741       turnFlag = ImgDecideSplitOrConjoin(info, vector, from, 0,
01742                                          relationArray, NIL(mdd_t),
01743                                          NIL(mdd_t), 1, depth);
01744     }
01745   } else {
01746     if (depth == turnDepth)
01747       turnFlag = 1;
01748     else
01749       turnFlag = 0;
01750   }
01751   if (turnFlag) {
01752     res = ImgImageByHybridWithStaticSplit(info, vector, from, relationArray,
01753                                           NIL(mdd_t), NIL(mdd_t));
01754     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01755                           (float)depth) / (float)(info->nLeaves + 1);
01756     if (depth > info->maxDepth)
01757       info->maxDepth = depth;
01758     info->nLeaves++;
01759     info->foundEssentialDepth = info->option->maxEssentialDepth;
01760     return(res);
01761   }
01762 
01763   if (info->option->findEssential) {
01764     if (info->option->findEssential == 1)
01765       findEssential = 1;
01766     else {
01767       if (depth >= info->lastFoundEssentialDepth)
01768         findEssential = 1;
01769       else
01770         findEssential = 0;
01771     }
01772   } else
01773     findEssential = 0;
01774   if (findEssential) {
01775     essentialCube = bdd_find_essential_cube(from);
01776 
01777     if (!bdd_is_tautology(essentialCube, 1)) {
01778       info->averageFoundEssential = (info->averageFoundEssential *
01779         (float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
01780         (float)(info->nFoundEssentials + 1);
01781       info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
01782         (float)info->nFoundEssentials + (float)depth) /
01783         (float)(info->nFoundEssentials + 1);
01784       if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
01785         info->topFoundEssentialDepth = depth;
01786       if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
01787         info->foundEssentials[depth]++;
01788       info->nFoundEssentials++;
01789       ImgVectorMinimize(info, vector, essentialCube, NIL(mdd_t), relationArray,
01790                         &tmpVector, &and_,
01791                         &tmpRelationArray, NIL(mdd_t *), NIL(mdd_t *));
01792       foundEssentialDepth = depth;
01793     } else {
01794       tmpVector = vector;
01795       tmpRelationArray = relationArray;
01796       and_ = NIL(mdd_t);
01797       foundEssentialDepth = info->option->maxEssentialDepth;
01798     }
01799     mdd_free(essentialCube);
01800     foundEssentialDepthT = info->option->maxEssentialDepth;
01801     foundEssentialDepthE = info->option->maxEssentialDepth;
01802   } else {
01803     tmpVector = vector;
01804     tmpRelationArray = relationArray;
01805     and_ = NIL(mdd_t);
01806     /* To remove compiler warnings */
01807     foundEssentialDepth = -1;
01808     foundEssentialDepthT = -1;
01809     foundEssentialDepthE = -1;
01810   }
01811 
01812   var = ImgChooseTrSplitVar(info, tmpVector, tmpRelationArray,
01813                             info->option->trSplitMethod,
01814                             info->option->piSplitFlag);
01815   if (!var) {
01816     res = ImgImageByHybridWithStaticSplit(info, vector, from, relationArray,
01817                                           NIL(mdd_t), NIL(mdd_t));
01818     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01819                           (float)depth) / (float)(info->nLeaves + 1);
01820     if (depth > info->maxDepth)
01821       info->maxDepth = depth;
01822     info->nLeaves++;
01823     info->foundEssentialDepth = info->option->maxEssentialDepth;
01824     return(res);
01825   }
01826 
01827   nRecur = 0;
01828   if (tmpVector) {
01829     ImgVectorConstrain(info, tmpVector, var, tmpRelationArray,
01830                         &vectorT, &cubeT, &newRelationArray,
01831                         NIL(mdd_t *), NIL(mdd_t *), TRUE);
01832   } else {
01833     vectorT = NIL(array_t);
01834     cubeT = NIL(mdd_t);
01835     newRelationArray = tmpRelationArray;
01836   }
01837   fromT = bdd_cofactor(from, var);
01838   relationArrayT = ImgGetCofactoredRelationArray(newRelationArray, var);
01839   if (relationArray && newRelationArray != tmpRelationArray)
01840     mdd_array_free(newRelationArray);
01841   if (!bdd_is_tautology(fromT, 0)) {
01842     resT = ImageByStaticInputSplit(info, vectorT, fromT,
01843                              relationArrayT, turnDepth, depth + 1);
01844     if (findEssential)
01845       foundEssentialDepthT = info->foundEssentialDepth;
01846     if (vectorT) {
01847       ImgVectorFree(vectorT);
01848       if (!bdd_is_tautology(cubeT, 1)) {
01849         tmp = resT;
01850         resT = mdd_and(tmp, cubeT, 1, 1);
01851         mdd_free(tmp);
01852       }
01853       mdd_free(cubeT);
01854     }
01855     nRecur++;
01856   } else {
01857     resT = mdd_zero(info->manager);
01858     if (vectorT) {
01859       ImgVectorFree(vectorT);
01860       mdd_free(cubeT);
01861     }
01862   }
01863   mdd_free(fromT);
01864   mdd_array_free(relationArrayT);
01865 
01866   if (bdd_is_tautology(resT, 1)) {
01867     mdd_free(var);
01868     if (vector && newRelationArray != relationArray)
01869       mdd_array_free(newRelationArray);
01870     res = resT;
01871     info->nEmptySubImage++;
01872   } else {
01873     varNot = mdd_not(var);
01874     mdd_free(var);
01875     if (tmpVector) {
01876       ImgVectorConstrain(info, tmpVector, varNot, tmpRelationArray,
01877                          &vectorE, &cubeE, &newRelationArray,
01878                          NIL(mdd_t *), NIL(mdd_t *), TRUE);
01879     } else {
01880       vectorE = NIL(array_t);
01881       cubeE = NIL(mdd_t);
01882       newRelationArray = tmpRelationArray;
01883     }
01884     fromE = bdd_cofactor(from, varNot);
01885     relationArrayE = ImgGetCofactoredRelationArray(newRelationArray, varNot);
01886     if (vector && newRelationArray != tmpRelationArray)
01887       mdd_array_free(newRelationArray);
01888     if (!bdd_is_tautology(fromE, 0)) {
01889       resE = ImageByStaticInputSplit(info, vectorE, fromE,
01890                                relationArrayE, turnDepth, depth + 1);
01891       if (findEssential)
01892         foundEssentialDepthE = info->foundEssentialDepth;
01893       if (vectorE) {
01894         ImgVectorFree(vectorE);
01895         if (!bdd_is_tautology(cubeE, 1)) {
01896           tmp = resE;
01897           resE = mdd_and(tmp, cubeE, 1, 1);
01898           mdd_free(tmp);
01899         }
01900         mdd_free(cubeE);
01901       }
01902       nRecur++;
01903     } else {
01904       resE = mdd_zero(info->manager);
01905       if (vectorE) {
01906         ImgVectorFree(vectorE);
01907         mdd_free(cubeE);
01908       }
01909     }
01910     mdd_free(fromE);
01911     mdd_array_free(relationArrayE);
01912     
01913     res = mdd_or(resT, resE, 1, 1);
01914     if (info->option->verbosity) {
01915       size = bdd_size(res);
01916       if (size > info->maxIntermediateSize)
01917         info->maxIntermediateSize = size;
01918       if (info->option->printBddSize) {
01919         fprintf(vis_stdout, "** tfm info: bdd_or(%d,%d) = %d\n",
01920                 bdd_size(resT), bdd_size(resE), size);
01921       }
01922     }
01923     mdd_free(resT);
01924     mdd_free(resE);
01925     mdd_free(varNot);
01926   }
01927 
01928   if (tmpVector && tmpVector != vector)
01929     ImgVectorFree(tmpVector);
01930   if (tmpRelationArray && tmpRelationArray != relationArray)
01931     mdd_array_free(tmpRelationArray);
01932 
01933   if (and_) {
01934     tmp = res;
01935     res = mdd_and(tmp, and_, 1, 1);
01936     if (info->option->verbosity) {
01937       size = bdd_size(res);
01938       if (size > info->maxIntermediateSize)
01939         info->maxIntermediateSize = size;
01940       if (info->option->printBddSize) {
01941         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
01942                 bdd_size(tmp), bdd_size(and_), size);
01943       }
01944     }
01945     mdd_free(tmp);
01946   }
01947 
01948   if (info->option->debug) {
01949     refResult = ImgImageByHybridWithStaticSplit(info, vector, from,
01950                                                 relationArray,
01951                                                 NIL(mdd_t), NIL(mdd_t));
01952     assert(mdd_equal(refResult, res));
01953     mdd_free(refResult);
01954   }
01955 
01956   if (nRecur == 0) {
01957     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
01958                           (float)depth) / (float)(info->nLeaves + 1);
01959     if (depth > info->maxDepth)
01960       info->maxDepth = depth;
01961     info->nLeaves++;
01962   }
01963 
01964   if (findEssential) {
01965     if (foundEssentialDepth == info->option->maxEssentialDepth) {
01966       if (foundEssentialDepthT < foundEssentialDepthE)
01967         foundEssentialDepth = foundEssentialDepthT;
01968       else
01969         foundEssentialDepth = foundEssentialDepthE;
01970     }
01971     info->foundEssentialDepth = foundEssentialDepth;
01972   }
01973   return(res);
01974 }
01975 
01976 
01986 static mdd_t *
01987 ImageByOutputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
01988                    int depth)
01989 {
01990   array_t               *newVector;
01991   mdd_t                 *new_, *resT, *resE, *res, *resPart;
01992   mdd_t                 *constrain, *tmp, *func;
01993   int                   size, i, vectorSize;
01994   array_t               *vectorArray, *varArray;
01995   ImgComponent_t        *comp;
01996   int                   hit;
01997   int                   split, nGroups;
01998   mdd_t                 *product, *refResult;
01999 
02000   ImgVectorConstrain(info, vector, constraint, NIL(array_t),
02001                      &newVector, &res, NIL(array_t *),
02002                      NIL(mdd_t *), NIL(mdd_t *), FALSE);
02003 
02004   info->nRecursion++;
02005   if (info->nIntermediateVars)
02006     size = ImgVectorFunctionSize(newVector);
02007   else
02008     size = array_n(newVector);
02009   if (size <= 1) {
02010     ImgVectorFree(newVector);
02011     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
02012                           (float)depth) / (float)(info->nLeaves + 1);
02013     if (depth > info->maxDepth)
02014       info->maxDepth = depth;
02015     info->nLeaves++;
02016     return(res);
02017   }
02018 
02019   if (size == 2) {
02020     hit = 1;
02021     if (!info->imgCache ||
02022         !(resPart = ImgCacheLookupTable(info, info->imgCache, newVector,
02023                                         NIL(bdd_t)))) {
02024       hit = 0;
02025       resPart = ImageFast2(info, newVector);
02026       if (info->imgCache)
02027         ImgCacheInsertTable(info->imgCache, newVector, NIL(bdd_t), resPart);
02028     }
02029 
02030     if (info->option->debug) {
02031       refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
02032       assert(mdd_equal(refResult, resPart));
02033       mdd_free(refResult);
02034     }
02035     new_ = mdd_and(res, resPart, 1, 1);
02036     if (info->option->verbosity) {
02037       size = bdd_size(new_);
02038       if (size > info->maxIntermediateSize)
02039         info->maxIntermediateSize = size;
02040       if (info->option->printBddSize) {
02041         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
02042                 bdd_size(res), bdd_size(resPart), size);
02043       }
02044     }
02045     mdd_free(res);
02046     if (!info->imgCache || hit) {
02047       mdd_free(resPart);
02048       ImgVectorFree(newVector);
02049     }
02050     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
02051                           (float)depth) / (float)(info->nLeaves + 1);
02052     if (depth > info->maxDepth)
02053       info->maxDepth = depth;
02054     info->nLeaves++;
02055     return(new_);
02056   }
02057 
02058   if (info->imgCache) {
02059     resPart = ImgCacheLookupTable(info, info->imgCache, newVector, NIL(mdd_t));
02060     if (resPart) {
02061       if (info->option->debug) {
02062         refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
02063         assert(mdd_equal(refResult, resPart));
02064         mdd_free(refResult);
02065       }
02066       new_ = mdd_and(res, resPart, 1, 1);
02067       if (info->option->verbosity) {
02068         size = bdd_size(new_);
02069         if (size > info->maxIntermediateSize)
02070           info->maxIntermediateSize = size;
02071         if (info->option->printBddSize) {
02072           fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
02073                   bdd_size(res), bdd_size(resPart), size);
02074         }
02075       }
02076       mdd_free(res);
02077       mdd_free(resPart);
02078       res = new_;
02079       ImgVectorFree(newVector);
02080       return(res);
02081     }
02082   }
02083 
02084   /* compute disconnected component and best variable selection */
02085   vectorArray = array_alloc(array_t *, 0);
02086   varArray = array_alloc(array_t *, 0);
02087   nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, NIL(mdd_t), 1,
02088                                             info->option->outputSplit, 0,
02089                                             vectorArray, varArray, &product,
02090                                             NIL(array_t), NIL(array_t *),
02091                                             NIL(mdd_t *), NIL(mdd_t *));
02092   vectorSize = array_n(newVector);
02093   if ((!info->imgCache || nGroups <= 1) && !info->option->debug)
02094     ImgVectorFree(newVector);
02095   if (nGroups == 0) {
02096     array_free(vectorArray);
02097     array_free(varArray);
02098 
02099     if (info->option->debug) {
02100       refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
02101       assert(mdd_equal(refResult, product));
02102       mdd_free(refResult);
02103       ImgVectorFree(newVector);
02104     }
02105 
02106     new_ = mdd_and(res, product, 1, 1);
02107     if (info->option->verbosity) {
02108       size = bdd_size(new_);
02109       if (size > info->maxIntermediateSize)
02110         info->maxIntermediateSize = size;
02111       if (info->option->printBddSize) {
02112         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
02113                 bdd_size(res), bdd_size(product), size);
02114       }
02115     }
02116     mdd_free(res);
02117     mdd_free(product);
02118     res = new_;
02119 
02120     info->averageDepth = (info->averageDepth * (float)info->nLeaves +
02121                           (float)depth) / (float)(info->nLeaves + 1);
02122     if (depth > info->maxDepth)
02123       info->maxDepth = depth;
02124     info->nLeaves++;
02125     return(res);
02126   } else if (nGroups > 1) {
02127     if (info->nDecomps == 0 || depth < info->topDecomp)
02128       info->topDecomp = depth;
02129     if (info->nDecomps == 0 || vectorSize > info->maxDecomp)
02130       info->maxDecomp = vectorSize;
02131     info->averageDecomp = (info->averageDecomp * (float)info->nDecomps +
02132                           (float)nGroups) / (float)(info->nDecomps + 1);
02133     info->nDecomps++;
02134   }
02135 
02136   product = mdd_one(info->manager);
02137   for (i = 0; i < array_n(vectorArray); i++) {
02138     vector = array_fetch(array_t *, vectorArray, i);
02139 
02140     hit = 1;
02141     if (!info->imgCache || nGroups == 1 ||
02142         !(resPart = ImgCacheLookupTable(info, info->imgCache, vector,
02143                                         NIL(bdd_t)))) {
02144       hit = 0;
02145       if (info->nIntermediateVars)
02146         size = ImgVectorFunctionSize(vector);
02147       else
02148         size = array_n(vector);
02149       if (size == 1) {
02150         comp = array_fetch(ImgComponent_t *, vector, 0);
02151         if (array_n(vector) > 1)
02152           func = ImgGetComposedFunction(vector);
02153         else
02154           func = comp->func;
02155         if (bdd_is_tautology(func, 1))
02156           resPart = mdd_dup(comp->var);
02157         else if (bdd_is_tautology(func, 0))
02158           resPart = mdd_not(comp->var);
02159         else
02160           resPart = mdd_one(info->manager);
02161         if (array_n(vector) > 1)
02162           mdd_free(func);
02163         info->averageDepth = (info->averageDepth * (float)info->nLeaves +
02164                                 (float)depth) / (float)(info->nLeaves + 1);
02165         if (depth > info->maxDepth)
02166           info->maxDepth = depth;
02167         info->nLeaves++;
02168       } else if (size == 2) {
02169         resPart = ImageFast2(info, vector);
02170         info->averageDepth = (info->averageDepth * (float)info->nLeaves +
02171                                 (float)depth) / (float)(info->nLeaves + 1);
02172         if (depth > info->maxDepth)
02173           info->maxDepth = depth;
02174         info->nLeaves++;
02175       } else {
02176         split = array_fetch(int, varArray, i);
02177         comp = array_fetch(ImgComponent_t *, vector, split);
02178         constrain = comp->func;
02179         resT = ImageByOutputSplit(info, vector, constrain, depth + 1);
02180         tmp = mdd_not(constrain);
02181         resE = ImageByOutputSplit(info, vector, tmp, depth + 1);
02182         mdd_free(tmp);
02183   
02184         resPart = bdd_ite(comp->var, resT, resE, 1, 1, 1);
02185         if (info->option->verbosity) {
02186           size = bdd_size(resPart);
02187           if (size > info->maxIntermediateSize)
02188             info->maxIntermediateSize = size;
02189           if (info->option->printBddSize) {
02190             fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
02191                     bdd_size(resT), bdd_size(resE), size);
02192           }
02193         }
02194         mdd_free(resT);
02195         mdd_free(resE);
02196       }
02197       if (info->imgCache)
02198         ImgCacheInsertTable(info->imgCache, vector, NIL(bdd_t), resPart);
02199     }
02200     if (!info->imgCache || hit)
02201       ImgVectorFree(vector);
02202     new_ = mdd_and(product, resPart, 1, 1);
02203     if (info->option->verbosity) {
02204       size = bdd_size(new_);
02205       if (size > info->maxIntermediateSize)
02206         info->maxIntermediateSize = size;
02207       if (info->option->printBddSize) {
02208         fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
02209                 bdd_size(product), bdd_size(resPart), size);
02210       }
02211     }
02212     mdd_free(product);
02213     if (!info->imgCache || hit)
02214       mdd_free(resPart);
02215     product = new_;
02216   }
02217 
02218   array_free(vectorArray);
02219   array_free(varArray);
02220 
02221   if (info->imgCache && nGroups > 1) {
02222     ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t),
02223                         mdd_dup(product));
02224   }
02225 
02226   if (info->option->debug) {
02227     refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
02228     assert(mdd_equal(refResult, product));
02229     mdd_free(refResult);
02230     if (!info->imgCache || nGroups == 1)
02231       ImgVectorFree(newVector);
02232   }
02233 
02234   new_ = mdd_and(res, product, 1, 1);
02235   if (info->option->verbosity) {
02236     size = bdd_size(new_);
02237     if (size > info->maxIntermediateSize)
02238       info->maxIntermediateSize = size;
02239     if (info->option->printBddSize) {
02240       fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
02241               bdd_size(res), bdd_size(product), size);
02242     }
02243   }
02244   mdd_free(res);
02245   mdd_free(product);
02246   res = new_;
02247 
02248   return(res);
02249 }
02250 
02251 
02263 static int
02264 ImageDecomposeAndChooseSplitVar(ImgTfmInfo_t *info, array_t *vector,
02265                                 mdd_t *from, int splitMethod, int split,
02266                                 int piSplitFlag,
02267                                 array_t *vectorArray, array_t *varArray,
02268                                 mdd_t **singles, array_t *relationArray,
02269                                 array_t **newRelationArray,
02270                                 mdd_t **cofactorCube, mdd_t **abstractCube)
02271 {
02272   int                   i, j, f, index;
02273   int                   nGroups, nSingles, nChosen;
02274   int                   nVars, nFuncs, arraySize;
02275   char                  *varFlag;
02276   int                   *funcGroup;
02277   int                   *varOccur;
02278   int                   bestVar;
02279   int                   *stack, size;
02280   ImgComponent_t        *comp, *newComp;
02281   array_t               *partVector;
02282   char                  *stackFlag;
02283   char                  *support;
02284   mdd_t                 *func;
02285   int                   *varCost;
02286   int                   decompose;
02287   int                   res, constConstrain;
02288   mdd_t                 *tmp, *cofactor, *abstract, *nsVar;
02289   array_t               *tmpRelationArray;
02290   char                  *intermediateVarFlag;
02291   int                   *intermediateVarFuncMap;
02292 
02293   if (info->useConstraint && from && splitMethod == 0)
02294     decompose = 0;
02295   else
02296     decompose = 1;
02297 
02298   arraySize = array_n(vector);
02299   if (info->nIntermediateVars)
02300     nFuncs = ImgVectorFunctionSize(vector);
02301   else
02302     nFuncs = arraySize;
02303   nVars = info->nVars;
02304 
02305   *singles = mdd_one(info->manager);
02306   if (relationArray) {
02307     cofactor = mdd_one(info->manager);
02308     abstract = mdd_one(info->manager);
02309   } else {
02310     cofactor = NIL(mdd_t);
02311     abstract = NIL(mdd_t);
02312   }
02313 
02314   if (decompose) {
02315     funcGroup = ALLOC(int, arraySize);
02316     memset(funcGroup, 0, sizeof(int) * arraySize);
02317     varFlag = ALLOC(char, nVars);
02318     memset(varFlag, 0, sizeof(char) * nVars);
02319     stack = ALLOC(int, arraySize);
02320     stackFlag = ALLOC(char, arraySize);
02321     memset(stackFlag, 0, sizeof(char) * arraySize);
02322     if (arraySize > nFuncs) {
02323       intermediateVarFlag = ALLOC(char, nVars);
02324       memset(intermediateVarFlag, 0, sizeof(char) * nVars);
02325       intermediateVarFuncMap = ALLOC(int, nVars);
02326       memset(intermediateVarFuncMap, 0, sizeof(int) * nVars);
02327       for (i = 0; i < arraySize; i++) {
02328         comp = array_fetch(ImgComponent_t *, vector, i);
02329         if (comp->intermediate) {
02330           index = (int)bdd_top_var_id(comp->var);
02331           intermediateVarFlag[index] = 1;
02332           intermediateVarFuncMap[index] = i;
02333         }
02334       }
02335     } else {
02336       /* To remove compiler warnings */
02337       intermediateVarFlag = NIL(char);
02338       intermediateVarFuncMap = NIL(int);
02339     }
02340   } else {
02341     /* To remove compiler warnings */
02342     funcGroup = NIL(int);
02343     varFlag = NIL(char);
02344     stack = NIL(int);
02345     stackFlag = NIL(char);
02346     intermediateVarFlag = NIL(char);
02347     intermediateVarFuncMap = NIL(int);
02348   }
02349   varOccur = ALLOC(int, nVars);
02350   if (splitMethod == 0 && split > 0)
02351     varCost = ALLOC(int, nVars);
02352   else
02353     varCost = NIL(int);
02354 
02355   nGroups = 0;
02356   nSingles = 0;
02357   nChosen = 0;
02358   while (nChosen < nFuncs) {
02359     bestVar = -1;
02360     memset(varOccur, 0, sizeof(int) * nVars);
02361     if (varCost)
02362       memset(varCost, 0, sizeof(int) * nVars);
02363 
02364     if (decompose) {
02365       size = 0;
02366       for (i = 0; i < arraySize; i++) {
02367         if (funcGroup[i] == 0) {
02368           stack[0] = i;
02369           size = 1;
02370           stackFlag[i] = 1;
02371           break;
02372         }
02373       }
02374       assert(size == 1);
02375   
02376       while (size) {
02377         size--;
02378         f = stack[size];
02379         funcGroup[f] = nGroups + 1;
02380         comp = array_fetch(ImgComponent_t *, vector, f);
02381         nChosen++;
02382         if (nChosen == arraySize)
02383           break;
02384         support = comp->support;
02385         if (comp->intermediate) {
02386           index = (int)bdd_top_var_id(comp->var);
02387           support[index] = 1;
02388         }
02389         for (i = 0; i < nVars; i++) {
02390           if (!support[i])
02391             continue;
02392           varOccur[i]++;
02393           if (varFlag[i])
02394             continue;
02395           varFlag[i] = 1;
02396           for (j = 0; j < arraySize; j++) {
02397             if (j == f || stackFlag[j])
02398               continue;
02399             comp = array_fetch(ImgComponent_t *, vector, j);
02400             if (arraySize != nFuncs) {
02401               if (intermediateVarFlag[i] && comp->intermediate) {
02402                 index = (int)bdd_top_var_id(comp->var);
02403                 if (index == i) {
02404                   if (funcGroup[j] == 0) {
02405                     stack[size] = j;
02406                     size++;
02407                     stackFlag[j] = 1;
02408                   }
02409                   FindIntermediateSupport(vector, comp, nVars, nGroups,
02410                                           stack, stackFlag, funcGroup, &size,
02411                                           intermediateVarFlag,
02412                                           intermediateVarFuncMap);
02413                   continue;
02414                 }
02415               }
02416             }
02417             if (funcGroup[j])
02418               continue;
02419             if (comp->support[i]) {
02420               stack[size] = j;
02421               size++;
02422               stackFlag[j] = 1;
02423             }
02424           }
02425         }
02426         if (comp->intermediate) {
02427           index = (int)bdd_top_var_id(comp->var);
02428           support[index] = 0;
02429         }
02430       }
02431     } else {
02432       for (i = 0; i < arraySize; i++) {
02433         comp = array_fetch(ImgComponent_t *, vector, i);
02434         support = comp->support;
02435         for (j = 0; j < nVars; j++) {
02436           if (support[j])
02437             varOccur[j]++;
02438         }
02439       }
02440       nChosen = nFuncs;
02441     }
02442 
02443     nGroups++;
02444 
02445     /* Collect the functions which belong to the current group */
02446     partVector = array_alloc(ImgComponent_t *, 0);
02447     for (i = 0; i < arraySize; i++) {
02448       if (decompose == 0 || funcGroup[i] == nGroups) {
02449         comp = array_fetch(ImgComponent_t *, vector, i);
02450         newComp = ImgComponentCopy(info, comp);
02451         array_insert_last(ImgComponent_t *, partVector, newComp);
02452       }
02453     }
02454     if (arraySize == nFuncs)
02455       size = array_n(partVector);
02456     else
02457       size = ImgVectorFunctionSize(partVector);
02458     if (size == 1) {
02459       nSingles++;
02460       if (size == array_n(partVector)) {
02461         comp = array_fetch(ImgComponent_t *, partVector, 0);
02462         func = comp->func;
02463       } else {
02464         comp = ImgGetLatchComponent(partVector);
02465         func = ImgGetComposedFunction(partVector);
02466       }
02467       if (from) {
02468         constConstrain = ImgConstConstrain(func, from);
02469         if (constConstrain == 1)
02470           res = 1;
02471         else if (constConstrain == 0)
02472           res = 0;
02473         else
02474           res = 2;
02475       } else {
02476         if (bdd_is_tautology(func, 1))
02477           res = 1;
02478         else if (bdd_is_tautology(func, 0))
02479           res = 0;
02480         else
02481           res = 2;
02482       }
02483       if (size != array_n(partVector))
02484         mdd_free(func);
02485       if (res == 1) {
02486         tmp = *singles;
02487         *singles = mdd_and(tmp, comp->var, 1, 1);
02488         mdd_free(tmp);
02489       } else if (res == 0) {
02490         tmp = *singles;
02491         *singles = mdd_and(tmp, comp->var, 1, 0);
02492         mdd_free(tmp);
02493       }
02494       if (abstract) {
02495         nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
02496         tmp = abstract;
02497         abstract = mdd_and(tmp, nsVar, 1, 1);
02498         mdd_free(tmp);
02499         mdd_free(nsVar);
02500       }
02501 
02502       ImgVectorFree(partVector);
02503       continue;
02504     }
02505 
02506     array_insert_last(array_t *, vectorArray, partVector);
02507 
02508     if (splitMethod == 0) { /* input splitting */
02509       if (decompose) {
02510         if (info->option->findDecompVar) {
02511           bestVar = FindDecomposableVariable(info, partVector);
02512           if (bestVar != -1)
02513             split = -1;
02514         }
02515       } else if (from) {
02516         comp = ImgComponentAlloc(info);
02517         comp->func = from;
02518         ImgComponentGetSupport(comp);
02519         for (i = 0; i < nVars; i++) {
02520           if (comp->support[i])
02521             varOccur[i]++;
02522         }
02523         comp->func = NIL(mdd_t);
02524         ImgComponentFree(comp);
02525       }
02526 
02527       if (split != -1) {
02528         bestVar = ChooseInputSplittingVariable(info, partVector, from,
02529                         info->option->inputSplit, decompose,
02530                         info->option->piSplitFlag, varOccur);
02531 
02532       }
02533     } else { /* output splitting */
02534       bestVar = ChooseOutputSplittingVariable(info, partVector,
02535                         info->option->outputSplit);
02536     }
02537     assert(bestVar != -1);
02538     array_insert_last(int, varArray, bestVar);
02539   }
02540 
02541   if (newRelationArray)
02542     *newRelationArray = relationArray;
02543   if (cofactorCube && abstractCube) {
02544     if (cofactor)
02545       *cofactorCube = cofactor;
02546     if (abstract)
02547       *abstractCube = abstract;
02548   } else {
02549     if (cofactor) {
02550       if (bdd_is_tautology(cofactor, 1))
02551         mdd_free(cofactor);
02552       else {
02553         *newRelationArray = ImgGetCofactoredRelationArray(relationArray,
02554                                                           cofactor);
02555         mdd_free(cofactor);
02556       }
02557     }
02558     if (abstract) {
02559       if (bdd_is_tautology(abstract, 1))
02560         mdd_free(abstract);
02561       else {
02562         tmpRelationArray = *newRelationArray;
02563         *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
02564                                                           tmpRelationArray,
02565                                                           abstract);
02566         mdd_free(abstract);
02567         if (tmpRelationArray != relationArray)
02568           mdd_array_free(tmpRelationArray);
02569       }
02570     }
02571   }
02572 
02573   if (decompose) {
02574     FREE(stackFlag);
02575     FREE(stack);
02576     FREE(funcGroup);
02577     FREE(varFlag);
02578     if (arraySize > nFuncs) {
02579       FREE(intermediateVarFlag);
02580       FREE(intermediateVarFuncMap);
02581     }
02582   }
02583   FREE(varOccur);
02584   if (varCost)
02585     FREE(varCost);
02586   nGroups -= nSingles;
02587   return(nGroups);
02588 }
02589 
02590 
02602 static mdd_t *
02603 ImageFast2(ImgTfmInfo_t *info, array_t *vector)
02604 {
02605   mdd_t                 *f1, *f2;
02606   int                   f21n, f21p;
02607   mdd_t                 *res, *resp, *resn;
02608   mdd_t                 *i1, *i2;
02609   ImgComponent_t        *comp;
02610   mdd_t                 *refResult;
02611   int                   i, freeFlag, size;
02612   array_t               *varArray, *funcArray;
02613 
02614   assert(ImgVectorFunctionSize(vector) == 2);
02615 
02616   if (info->option->debug)
02617     refResult = ImgImageByHybrid(info, vector, NIL(mdd_t));
02618   else
02619     refResult = NIL(mdd_t);
02620 
02621   if (array_n(vector) == 2) {
02622     comp = array_fetch(ImgComponent_t *, vector, 0);
02623     f1 = comp->func;
02624     i1 = comp->var;
02625 
02626     comp = array_fetch(ImgComponent_t *, vector, 1);
02627     f2 = comp->func;
02628     i2 = comp->var;
02629 
02630     freeFlag = 0;
02631   } else {
02632     varArray = array_alloc(mdd_t *, 0);
02633     funcArray = array_alloc(mdd_t *, 0);
02634 
02635     i1 = NIL(mdd_t);
02636     i2 = NIL(mdd_t);
02637     f1 = NIL(mdd_t);
02638     f2 = NIL(mdd_t);
02639 
02640     for (i = 0; i < array_n(vector); i++) {
02641       comp = array_fetch(ImgComponent_t *, vector, i);
02642       if (comp->intermediate) {
02643         array_insert_last(mdd_t *, varArray, comp->var);
02644         array_insert_last(mdd_t *, funcArray, comp->func);
02645         continue;
02646       }
02647       if (f1) {
02648         f2 = comp->func;
02649         i2 = comp->var;
02650       } else {
02651         f1 = comp->func;
02652         i1 = comp->var;
02653       }
02654     }
02655 
02656     f1 = bdd_vector_compose(f1, varArray, funcArray);
02657     f2 = bdd_vector_compose(f2, varArray, funcArray);
02658     array_free(varArray);
02659     array_free(funcArray);
02660     freeFlag = 1;
02661   }
02662 
02663   ImgCheckConstConstrain(f1, f2, &f21p, &f21n);
02664 
02665   if (f21p == 1)
02666     resp = mdd_dup(i2);
02667   else if (f21p == 0)
02668     resp = mdd_not(i2);
02669   else
02670     resp = mdd_one(info->manager);
02671 
02672   if (f21n == 1)
02673     resn = mdd_dup(i2);
02674   else if (f21n == 0)
02675     resn = mdd_not(i2);
02676   else
02677     resn = mdd_one(info->manager);
02678 
02679   /* merge final result */
02680   res = bdd_ite(i1, resp, resn, 1, 1, 1);
02681   if (info->option->verbosity) {
02682     size = bdd_size(res);
02683     if (size > info->maxIntermediateSize)
02684       info->maxIntermediateSize = size;
02685     if (info->option->printBddSize) {
02686       fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
02687                 bdd_size(resp), bdd_size(resn), size);
02688     }
02689   }
02690   mdd_free(resp);
02691   mdd_free(resn);
02692   if (freeFlag) {
02693     mdd_free(f1);
02694     mdd_free(f2);
02695   }
02696 
02697   if (info->option->debug) {
02698     assert(mdd_equal(refResult, res));
02699     mdd_free(refResult);
02700   }
02701 
02702   return(res);
02703 }
02704 
02705 
02715 static int
02716 FindDecomposableVariable(ImgTfmInfo_t *info, array_t *vector)
02717 {
02718   int                   i, j, f, split;
02719   int                   nChosen, index, varId;
02720   int                   nVars, nFuncs;
02721   char                  *varFlag;
02722   int                   *funcGroup;
02723   int                   *stack, size;
02724   ImgComponent_t        *comp;
02725   char                  *stackFlag;
02726   char                  *support;
02727   int                   arraySize;
02728   char                  *intermediateVarFlag;
02729   int                   *intermediateVarFuncMap;
02730 
02731   arraySize = array_n(vector);
02732   if (info->nIntermediateVars)
02733     nFuncs = ImgVectorFunctionSize(vector);
02734   else
02735     nFuncs = arraySize;
02736   nVars = info->nVars;
02737 
02738   funcGroup = ALLOC(int, arraySize);
02739   varFlag = ALLOC(char, nVars);
02740   stack = ALLOC(int, arraySize);
02741   stackFlag = ALLOC(char, arraySize);
02742 
02743   if (arraySize > nFuncs) {
02744     intermediateVarFlag = ALLOC(char, nVars);
02745     memset(intermediateVarFlag, 0, sizeof(char) * nVars);
02746     intermediateVarFuncMap = ALLOC(int, nVars);
02747     memset(intermediateVarFuncMap, 0, sizeof(int) * nVars);
02748     for (i = 0; i < arraySize; i++) {
02749       comp = array_fetch(ImgComponent_t *, vector, i);
02750       if (comp->intermediate) {
02751         index = (int)bdd_top_var_id(comp->var);
02752         intermediateVarFlag[index] = 1;
02753         intermediateVarFuncMap[index] = i;
02754       }
02755     }
02756   } else {
02757     intermediateVarFlag = NIL(char);
02758     intermediateVarFuncMap = NIL(int);
02759   }
02760 
02761   varId = -1;
02762   for (split = 0; split < nVars; split++) {
02763     if (intermediateVarFlag[split])
02764       continue;
02765 
02766     memset(funcGroup, 0, sizeof(int) * arraySize);
02767     memset(varFlag, 0, sizeof(char) * nVars);
02768     memset(stackFlag, 0, sizeof(char) * arraySize);
02769 
02770     varFlag[split] = 1;
02771     nChosen = 0;
02772   
02773     stack[0] = 0;
02774     size = 1;
02775     stackFlag[0] = 1;
02776   
02777     while (size) {
02778       size--;
02779       f = stack[size];
02780       funcGroup[f] = 1;
02781       comp = array_fetch(ImgComponent_t *, vector, f);
02782       nChosen++;
02783       if (nChosen == arraySize)
02784         break;
02785       support = comp->support;
02786       if (comp->intermediate) {
02787         index = (int)bdd_top_var_id(comp->var);
02788         support[index] = 1;
02789       }
02790       for (i = 0; i < nVars; i++) {
02791         if (!support[i])
02792           continue;
02793         if (varFlag[i])
02794           continue;
02795         varFlag[i] = 1;
02796         for (j = 0; j < nFuncs; j++) {
02797           if (j == f || stackFlag[j])
02798             continue;
02799           comp = array_fetch(ImgComponent_t *, vector, j);
02800           if (arraySize != nFuncs) {
02801             if (intermediateVarFlag[i] && comp->intermediate) {
02802               index = (int)bdd_top_var_id(comp->var);
02803               if (index == i) {
02804                 if (funcGroup[j] == 0) {
02805                   stack[size] = j;
02806                   size++;
02807                   stackFlag[j] = 1;
02808                 }
02809                 FindIntermediateSupport(vector, comp, nVars, 0,
02810                                         stack, stackFlag, funcGroup, &size,
02811                                         intermediateVarFlag,
02812                                         intermediateVarFuncMap);
02813                 continue;
02814               }
02815             }
02816           }
02817           if (funcGroup[j])
02818             continue;
02819           if (comp->support[i]) {
02820             stack[size] = j;
02821             size++;
02822             stackFlag[j] = 1;
02823           }
02824         }
02825       }
02826       if (comp->intermediate) {
02827         index = (int)bdd_top_var_id(comp->var);
02828         support[index] = 0;
02829       }
02830     }
02831 
02832     if (nChosen < nFuncs) {
02833       varId = split;
02834       break;
02835     }
02836   }
02837 
02838   FREE(stackFlag);
02839   FREE(stack);
02840   FREE(funcGroup);
02841   FREE(varFlag);
02842   if (arraySize > nFuncs) {
02843     FREE(intermediateVarFlag);
02844     FREE(intermediateVarFuncMap);
02845   }
02846 
02847   return(varId);
02848 }
02849 
02850 
02860 static int
02861 TfmCheckImageValidity(ImgTfmInfo_t *info, mdd_t *image)
02862 {
02863   int           i, id;
02864   array_t       *supportIds;
02865   int           status = 1;
02866 
02867   supportIds = mdd_get_bdd_support_ids(info->manager, image);
02868   for (i = 0; i < array_n(supportIds); i++) {
02869     id = array_fetch(int, supportIds, i);
02870     if (st_lookup(info->quantifyVarsTable, (char *)(long)id, NIL(char *))) {
02871       fprintf(vis_stderr,
02872               "** tfm error: image contains a primary input variable (%d)\n",
02873               id);
02874       status = 0;
02875     }
02876     if (st_lookup(info->rangeVarsTable, (char *)(long)id, NIL(char *))) {
02877       fprintf(vis_stderr,
02878               "** tfm error: image contains a range variable (%d)\n", id);
02879       status = 0;
02880     }
02881     if (info->intermediateVarsTable &&
02882         st_lookup(info->intermediateVarsTable, (char *)(long)id, NIL(char *))) {
02883       fprintf(vis_stderr,
02884               "** tfm error: image contains an intermediate variable (%d)\n",
02885               id);
02886       status = 0;
02887     }
02888   }
02889   array_free(supportIds);
02890   return(status);
02891 }
02892 
02893 
02906 static void
02907 FindIntermediateSupport(array_t *vector, ImgComponent_t *comp,
02908                         int nVars, int nGroups,
02909                         int *stack, char *stackFlag, int *funcGroup, int *size,
02910                         char *intermediateVarFlag, int *intermediateVarFuncMap)
02911 {
02912   int                   i, f;
02913   ImgComponent_t        *intermediateComp;
02914 
02915   for (i = 0; i < nVars; i++) {
02916     if (comp->support[i]) {
02917       if (intermediateVarFlag[i]) {
02918         f = intermediateVarFuncMap[i];
02919         if (stackFlag[f] || funcGroup[f] == nGroups + 1)
02920           continue;
02921         stack[*size] = f;
02922         (*size)++;
02923         stackFlag[f] = 1;
02924 
02925         intermediateComp = array_fetch(ImgComponent_t *, vector, f);
02926         FindIntermediateSupport(vector, intermediateComp, nVars, nGroups,
02927                                 stack, stackFlag, funcGroup, size,
02928                                 intermediateVarFlag, intermediateVarFuncMap);
02929       }
02930     }
02931   }
02932 }
02933 
02934 
02944 static void
02945 PrintVectorDecomposition(ImgTfmInfo_t *info, array_t *vectorArray,
02946                          array_t *varArray)
02947 {
02948   int                   i, j, n;
02949   int                   var, index;
02950   ImgComponent_t        *comp;
02951   array_t               *vector;
02952 
02953   fprintf(vis_stdout, "** tfm info: vector decomposition\n");
02954   n = array_n(vectorArray);
02955   for (i = 0; i < n; i++) {
02956     vector = array_fetch(array_t *, vectorArray, i);
02957     var = array_fetch(int, varArray, i);
02958     fprintf(vis_stdout, "Group[%d] : num = %d, split = %d\n",
02959             i, array_n(vector), var);
02960     for (j = 0; j < array_n(vector); j++) {
02961       comp = array_fetch(ImgComponent_t *, vector, j);
02962       index = (int)bdd_top_var_id(comp->var);
02963       fprintf(vis_stdout, " %d", index);
02964     }
02965     fprintf(vis_stdout, "\n");
02966   }
02967 }
02968 
02969 
02982 static int
02983 CheckIfValidSplitOrGetNew(ImgTfmInfo_t *info, int split, array_t *vector,
02984                         array_t *relationArray, mdd_t *from)
02985 {
02986   int newSplit = split;
02987   int i, j, nVars;
02988   ImgComponent_t *comp;
02989   char *support;
02990   int *varOccur;
02991   int decompose;
02992 
02993   nVars = info->nVars;
02994   support = ALLOC(char, sizeof(char) * nVars);
02995   memset(support, 0, sizeof(char) * nVars);
02996 
02997   comp = ImgComponentAlloc(info);
02998   for (i = 0; i < array_n(relationArray); i++) {
02999     comp->func = array_fetch(mdd_t *, relationArray, i);;
03000     ImgSupportClear(info, comp->support);
03001     ImgComponentGetSupport(comp);
03002     for (j = 0; j < nVars; j++) {
03003       if (comp->support[j]) {
03004         if (j == split) {
03005           comp->func = NIL(mdd_t);
03006           ImgComponentFree(comp);
03007           FREE(support);
03008           return(split);
03009         }
03010         support[j] = 1;
03011       }
03012     }
03013   }
03014 
03015   comp->func = NIL(mdd_t);
03016   ImgComponentFree(comp);
03017 
03018   if (info->useConstraint && from)
03019     decompose = 0;
03020   else
03021     decompose = 1;
03022 
03023   varOccur = ALLOC(int, nVars);
03024   memset(varOccur, 0, sizeof(int) * nVars);
03025 
03026   if (from) {
03027     comp = ImgComponentAlloc(info);
03028     comp->func = from;
03029     ImgComponentGetSupport(comp);
03030     for (i = 0; i < nVars; i++) {
03031       if (comp->support[i])
03032         varOccur[i]++;
03033     }
03034     comp->func = NIL(mdd_t);
03035     ImgComponentFree(comp);
03036   }
03037 
03038   FREE(support);
03039 
03040   newSplit = ChooseInputSplittingVariable(info, vector, from,
03041                 info->option->inputSplit, decompose,
03042                 info->option->piSplitFlag, varOccur);
03043 
03044   FREE(varOccur);
03045 
03046   return(newSplit);
03047 }
03048 
03049 
03059 static int
03060 ChooseInputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
03061                 int splitMethod, int decompose, int piSplitFlag, int *varOccur)
03062 {
03063   int nVars = info->nVars;
03064   int bestVar = -1;
03065   int secondBestVar = -1;
03066   int bestCost, newCost;
03067   int bestOccur, tieCount;
03068   int secondBestOccur, secondTieCount;
03069   int i, j;
03070   ImgComponent_t *comp;
03071   mdd_t *var, *varNot, *pcFunc, *ncFunc;
03072   int *varCost;
03073   int size = ImgVectorFunctionSize(vector);
03074 
03075   if (info->option->inputSplit > 0) {
03076     varCost = ALLOC(int, nVars);
03077     memset(varCost, 0, sizeof(int) * nVars);
03078   } else
03079     varCost = NIL(int);
03080 
03081   switch (splitMethod) {
03082   case 0:
03083     /* Find the most frequently occurred variable */
03084     bestOccur = 0;
03085     tieCount = 0;
03086     secondBestOccur = 0;
03087     secondTieCount = 0;
03088   
03089     for (i = 0; i < nVars; i++) {
03090       if (varOccur[i] == 0)
03091         continue;
03092       if (piSplitFlag == 0) {
03093         if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
03094                       NIL(char *))) {
03095           if ((bestOccur == 0 && secondBestOccur == 0) ||
03096               (varOccur[i] > bestOccur && varOccur[i] > secondBestOccur)) {
03097             secondBestOccur = varOccur[i];
03098             secondBestVar = i;
03099             secondTieCount = 1;
03100           } else if (secondBestOccur > bestOccur &&
03101                      varOccur[i] == secondBestOccur) {
03102             secondTieCount++;
03103             if (info->option->tieBreakMode == 0 &&
03104                 bdd_get_level_from_id(info->manager, i) <
03105                 bdd_get_level_from_id(info->manager, secondBestVar)) {
03106               secondBestVar = i;
03107             }
03108           }
03109           continue;
03110         }
03111       }
03112       if (size < array_n(vector) &&
03113           st_lookup(info->intermediateVarsTable, (char *)(long)i,
03114                     NIL(char *))) {
03115         continue;
03116       }
03117       if (bestOccur == 0 || varOccur[i] > bestOccur) {
03118         bestOccur = varOccur[i];
03119         bestVar = i;
03120         tieCount = 1;
03121       } else if (varOccur[i] == bestOccur) {
03122         tieCount++;
03123         if (info->option->tieBreakMode == 0 &&
03124             bdd_get_level_from_id(info->manager, i) <
03125             bdd_get_level_from_id(info->manager, bestVar)) {
03126           bestVar = i;
03127         }
03128       }
03129     }
03130 
03131     if (piSplitFlag == 0 && bestVar == -1) {
03132       bestVar = secondBestVar;
03133       bestOccur = secondBestOccur;
03134       tieCount = secondTieCount;
03135     }
03136   
03137     if (info->option->tieBreakMode == 1 && tieCount > 1) {
03138       bestCost = IMG_TF_MAX_INT;
03139       for (i = bestVar; i < nVars; i++) {
03140         if (varOccur[i] != bestOccur)
03141           continue;
03142         if (size < array_n(vector) &&
03143             st_lookup(info->intermediateVarsTable, (char *)(long)i,
03144                       NIL(char *))) {
03145           continue;
03146         }
03147         var = bdd_var_with_index(info->manager, i);
03148         newCost = 0;
03149         for (j = 0; j < array_n(vector); j++) {
03150           comp = array_fetch(ImgComponent_t *, vector, j);
03151           newCost += bdd_estimate_cofactor(comp->func, var, 1);
03152           newCost += bdd_estimate_cofactor(comp->func, var, 0);
03153         }
03154         if (decompose == 0) {
03155           newCost += bdd_estimate_cofactor(from, var, 1);
03156           newCost += bdd_estimate_cofactor(from, var, 0);
03157         }
03158         mdd_free(var);
03159   
03160         if (newCost < bestCost) {
03161           bestVar = i;
03162           bestCost = newCost;
03163         } else if (newCost == bestCost) {
03164           if (bdd_get_level_from_id(info->manager, i) <
03165               bdd_get_level_from_id(info->manager, bestVar)) {
03166             bestVar = i;
03167           }
03168         }
03169       }
03170     }
03171     break;
03172   case 1:
03173     /* Find the variable which makes the smallest support after splitting */
03174     bestCost = IMG_TF_MAX_INT;
03175     for (i = 0; i < nVars; i++) {
03176       if (varOccur[i] == 0)
03177         continue;
03178       if (size < array_n(vector) &&
03179           st_lookup(info->intermediateVarsTable, (char *)(long)i,
03180                     NIL(char *))) {
03181         continue;
03182       }
03183       var = bdd_var_with_index(info->manager, i);
03184       varNot = mdd_not(var);
03185       for (j = 0; j < array_n(vector); j++) {
03186         comp = array_fetch(ImgComponent_t *, vector, j);
03187         pcFunc = bdd_cofactor(comp->func, var);
03188         varCost[i] += ImgCountBddSupports(pcFunc);
03189         mdd_free(pcFunc);
03190         ncFunc = bdd_cofactor(comp->func, varNot);
03191         varCost[i] += ImgCountBddSupports(ncFunc);
03192         mdd_free(ncFunc);
03193       }
03194       if (decompose == 0) {
03195         pcFunc = bdd_cofactor(from, var);
03196         varCost[i] += ImgCountBddSupports(pcFunc);
03197         mdd_free(pcFunc);
03198         ncFunc = bdd_cofactor(from, varNot);
03199         varCost[i] += ImgCountBddSupports(ncFunc);
03200         mdd_free(ncFunc);
03201       }
03202       mdd_free(var);
03203       mdd_free(varNot);
03204   
03205       if (varCost[i] < bestCost) {
03206         bestCost = varCost[i];
03207         bestVar = i;
03208       } else if (varCost[i] == bestCost) {
03209         if (varOccur[i] < varOccur[bestVar]) {
03210           bestVar = i;
03211         } else if (varOccur[i] == varOccur[bestVar]) {
03212           if (bdd_get_level_from_id(info->manager, i) <
03213               bdd_get_level_from_id(info->manager, bestVar)) {
03214             bestVar = i;
03215           }
03216         }
03217       }
03218     }
03219     break;
03220   case 2:
03221     /* Find the variable which makes the smallest BDDs of all functions
03222        after splitting */
03223     bestCost = IMG_TF_MAX_INT;
03224     for (i = 0; i < nVars; i++) {
03225       if (varOccur[i] == 0)
03226         continue;
03227       if (size < array_n(vector) &&
03228           st_lookup(info->intermediateVarsTable, (char *)(long)i,
03229                     NIL(char *))) {
03230         continue;
03231       }
03232       var = bdd_var_with_index(info->manager, i);
03233       for (j = 0; j < array_n(vector); j++) {
03234         comp = array_fetch(ImgComponent_t *, vector, j);
03235         varCost[i] += bdd_estimate_cofactor(comp->func, var, 1);
03236         varCost[i] += bdd_estimate_cofactor(comp->func, var, 0);
03237       }
03238       if (decompose == 0) {
03239         varCost[i] += bdd_estimate_cofactor(from, var, 1);
03240         varCost[i] += bdd_estimate_cofactor(from, var, 0);
03241       }
03242       mdd_free(var);
03243   
03244       if (varCost[i] < bestCost) {
03245         bestCost = varCost[i];
03246         bestVar = i;
03247       } else if (varCost[i] == bestCost) {
03248         if (varOccur[i] < varOccur[bestVar]) {
03249           bestVar = i;
03250         } else if (varOccur[i] == varOccur[bestVar]) {
03251           if (bdd_get_level_from_id(info->manager, i) <
03252               bdd_get_level_from_id(info->manager, bestVar)) {
03253             bestVar = i;
03254           }
03255         }
03256       }
03257     }
03258     break;
03259   case 3: /* top variable */
03260     for (i = 0; i < nVars; i++) {
03261       if (varOccur[i] == 0)
03262         continue;
03263       if (size < array_n(vector) &&
03264           st_lookup(info->intermediateVarsTable, (char *)(long)i,
03265                     NIL(char *))) {
03266         continue;
03267       }
03268       if (piSplitFlag == 0) {
03269         if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
03270                       NIL(char *))) {
03271           if (bestVar == -1 && secondBestVar == -1)
03272             secondBestVar = i;
03273           else if (bdd_get_level_from_id(info->manager, i) <
03274                    bdd_get_level_from_id(info->manager, secondBestVar)) {
03275             secondBestVar = i;
03276           }
03277           continue;
03278         }
03279       }
03280       if (bestVar == -1 ||
03281           bdd_get_level_from_id(info->manager, i) <
03282           bdd_get_level_from_id(info->manager, bestVar)) {
03283         bestVar = i;
03284       }
03285     }
03286 
03287     if (piSplitFlag == 0 && bestVar == -1)
03288       bestVar = secondBestVar;
03289     break;
03290   default:
03291     break;
03292   }
03293 
03294   if (varCost)
03295     FREE(varCost);
03296 
03297   return(bestVar);
03298 }
03299 
03300 
03310 static int
03311 ChooseOutputSplittingVariable(ImgTfmInfo_t *info, array_t *vector,
03312                         int splitMethod)
03313 {
03314   int bestVar = -1;
03315   int bestCost, newCost;
03316   int i;
03317   ImgComponent_t *comp;
03318   int size = ImgVectorFunctionSize(vector);
03319   int index;
03320 
03321   switch (splitMethod) {
03322   case 0: /* smallest */
03323     bestCost = IMG_TF_MAX_INT;
03324     for (i = 0; i < array_n(vector); i++) {
03325       comp = array_fetch(ImgComponent_t *, vector, i);
03326       if (size < array_n(vector) &&
03327           st_lookup(info->intermediateVarsTable,
03328                     (char *)(long)bdd_top_var_id(comp->var), NIL(char *))) {
03329         continue;
03330       }
03331       newCost = bdd_size(comp->func);
03332       if (newCost < bestCost) {
03333         bestVar = i;
03334         bestCost = newCost;
03335       }
03336     }
03337     break;
03338   case 1: /* largest */
03339     bestCost = 0;
03340     for (i = 0; i < array_n(vector); i++) {
03341       comp = array_fetch(ImgComponent_t *, vector, i);
03342       if (size < array_n(vector) &&
03343           st_lookup(info->intermediateVarsTable,
03344                     (char *)(long)bdd_top_var_id(comp->var), NIL(char *))) {
03345         continue;
03346       }
03347       newCost = bdd_size(comp->func);
03348       if (newCost > bestCost) {
03349         bestVar = i;
03350         bestCost = newCost;
03351       }
03352     }
03353     break;
03354   case 2: /* top variable */
03355   default:
03356     comp = array_fetch(ImgComponent_t *, vector, 0);
03357     bestVar = (int)bdd_top_var_id(comp->var);
03358     for (i = 0; i < array_n(vector); i++) {
03359       comp = array_fetch(ImgComponent_t *, vector, i);
03360       index = (int)bdd_top_var_id(comp->var);
03361       if (size < array_n(vector) &&
03362           st_lookup(info->intermediateVarsTable, (char *)(long)index,
03363                     NIL(char *))) {
03364         continue;
03365       }
03366       if (bestVar == -1 ||
03367           bdd_get_level_from_id(info->manager, index) <
03368           bdd_get_level_from_id(info->manager, bestVar)) {
03369         bestVar = i;
03370       }
03371     }
03372     break;
03373   }
03374 
03375   return(bestVar);
03376 }