VIS

src/img/imgTfmBwd.c File Reference

#include "imgInt.h"
Include dependency graph for imgTfmBwd.c:

Go to the source code of this file.

Functions

static bdd_t * PreImageByDomainCofactoring (ImgTfmInfo_t *info, array_t *delta, bdd_t *image, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int splitMethod, int turnDepth, int depth)
static mdd_t * PreImageByStaticDomainCofactoring (ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, int turnDepth, int depth)
static bdd_t * PreImageByConstraintCofactoring (ImgTfmInfo_t *info, array_t *delta, bdd_t *image, int splitMethod, int turnDepth, int depth)
static mdd_t * PreImageBySubstitution (ImgTfmInfo_t *info, array_t *vector, mdd_t *from)
static bdd_t * PreImageMakeVectorCanonical (ImgTfmInfo_t *info, array_t *vector, bdd_t *image, array_t *relationArray, array_t **newVector, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube)
static bdd_t * PreImageMakeRelationCanonical (ImgTfmInfo_t *info, array_t *vector, bdd_t *image, array_t *relationArray, array_t **newVector, array_t **newRelationArray)
static bdd_t * PreImageDeleteOneComponent (ImgTfmInfo_t *info, array_t *delta, int index, array_t **newDelta)
static int PreImageChooseSplitVar (ImgTfmInfo_t *info, array_t *delta, bdd_t *img, int splitMethod, int split)
static mdd_t * DomainCofactoring (ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, mdd_t *c, array_t **newVector, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube)
static int CheckPreImageVector (ImgTfmInfo_t *info, array_t *vector, mdd_t *image)
bdd_t * ImgTfmPreImage (ImgTfmInfo_t *info, bdd_t *image)

Variables

static char rcsid[] UNUSED = "$Id: imgTfmBwd.c,v 1.29 2002/08/18 04:47:07 fabio Exp $"

Function Documentation

static int CheckPreImageVector ( ImgTfmInfo_t *  info,
array_t *  vector,
mdd_t *  image 
) [static]

Function********************************************************************

Synopsis [Checks sanity of a vector for preimage.]

Description [Checks sanity of a vector for preimage.]

SideEffects []

Definition at line 2699 of file imgTfmBwd.c.

{
  ImgComponent_t        *comp, *imgComp;
  int                   i, id, size, status;

  status = 1;
  if (info->nIntermediateVars)
    size = ImgVectorFunctionSize(vector);
  else
    size = array_n(vector);
  if (size != mdd_get_number_of_bdd_support(info->manager, image)) {
    fprintf(vis_stderr,
            "** tfm error: function vector length is different. (%d != %d)\n",
            size, mdd_get_number_of_bdd_support(info->manager, image));
    status = 0;
  }

  imgComp = ImgComponentAlloc(info);
  imgComp->func = image;
  ImgComponentGetSupport(imgComp);
  for (i = 0; i < array_n(vector); i++) {
    comp = array_fetch(ImgComponent_t *, vector, i);
    id = (int)bdd_top_var_id(comp->var);
    if (comp->intermediate)
      imgComp->support[id] = 2;
    else if (imgComp->support[id] == 0) {
      fprintf(vis_stderr,
              "** tfm error: variable index[%d] is not in constraint\n", id);
      status = 0;
    } else
      imgComp->support[id] = 2;
  }
  for (i = 0; i < info->nVars; i++) {
    if (imgComp->support[i] == 1) {
      fprintf(vis_stderr,
            "** tfm error: variable index[%d] is not in function vector\n", i);
      status = 0;
    }
  }
  imgComp->func = NIL(mdd_t);
  ImgComponentFree(imgComp);
  return(status);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static mdd_t * DomainCofactoring ( ImgTfmInfo_t *  info,
array_t *  vector,
mdd_t *  from,
array_t *  relationArray,
mdd_t *  c,
array_t **  newVector,
array_t **  newRelationArray,
mdd_t **  cofactorCube,
mdd_t **  abstractCube 
) [static]

Function********************************************************************

Synopsis [Performs domain cofactoring on a vector and from set with respect to a variable.]

Description [Performs domain cofactoring on a vector and from set with respect to a variable.]

SideEffects []

Definition at line 2469 of file imgTfmBwd.c.

{
  mdd_t                 *res, *tmp;
  ImgComponent_t        *comp, *comp1;
  array_t               *vector1;
  int                   i, index, n, pos;
  mdd_t                 *newFrom, *var, *nsVar;
  mdd_t                 *cofactor, *abstract, *constIntermediate;
  array_t               *tmpRelationArray;
  st_table              *equivTable;
  int                   *ptr, *regularPtr;
  int                   size;

  newFrom = mdd_dup(from);
  vector1 = array_alloc(ImgComponent_t *, 0);

  if (relationArray) {
    cofactor = mdd_one(info->manager);
    abstract = mdd_one(info->manager);
  } else {
    cofactor = NIL(mdd_t);
    abstract = NIL(mdd_t);
  }

  if (info->nIntermediateVars) {
    size = ImgVectorFunctionSize(vector);
    if (size == array_n(vector))
      constIntermediate = NIL(mdd_t);
    else
      constIntermediate = mdd_one(info->manager);
  } else
    constIntermediate = NIL(mdd_t);

  n = 0;
  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
  index = (int)bdd_top_var_id(c);
  for (i = 0; i < array_n(vector); i++) {
    comp = array_fetch(ImgComponent_t *, vector, i);
    if (comp->support[index])
      res = bdd_cofactor(comp->func, c);
    else
      res = mdd_dup(comp->func);
    if (bdd_is_tautology(res, 1)) {
      if (comp->intermediate) {
        tmp = constIntermediate;
        constIntermediate = mdd_and(tmp, comp->var, 1, 1);
        mdd_free(tmp);
        mdd_free(res);
        continue;
      }
      tmp = newFrom;
      newFrom = bdd_cofactor(tmp, comp->var);
      mdd_free(tmp);
      mdd_free(res);
      if (relationArray) {
        nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
        tmp = abstract;
        abstract = mdd_and(tmp, nsVar, 1, 1);
        mdd_free(tmp);
        mdd_free(nsVar);
      }
    } else if (bdd_is_tautology(res, 0)) {
      if (comp->intermediate) {
        tmp = constIntermediate;
        constIntermediate = mdd_and(tmp, comp->var, 1, 0);
        mdd_free(tmp);
        mdd_free(res);
        continue;
      }
      tmp = newFrom;
      var = mdd_not(comp->var);
      newFrom = bdd_cofactor(tmp, var);
      mdd_free(tmp);
      mdd_free(var);
      mdd_free(res);
      if (relationArray) {
        nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
        tmp = abstract;
        abstract = mdd_and(tmp, nsVar, 1, 1);
        mdd_free(tmp);
        mdd_free(nsVar);
      }
    } else {
      if (comp->intermediate) {
        comp1 = ImgComponentAlloc(info);
        comp1->var = mdd_dup(comp->var);
        comp1->func = res;
        if (mdd_equal(res, comp->func))
          ImgSupportCopy(info, comp1->support, comp->support);
        else
          ImgComponentGetSupport(comp1);
        comp1->intermediate = 1;
        array_insert_last(ImgComponent_t *, vector1, comp1);
        n++;
        continue;
      }
      ptr = (int *)bdd_pointer(res);
      regularPtr = (int *)((unsigned long)ptr & ~01);
      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
        comp1 = array_fetch(ImgComponent_t *, vector1, pos);
        if (mdd_equal(res, comp1->func)) {
          tmp = newFrom;
          newFrom = bdd_compose(tmp, comp->var, comp1->var);
          mdd_free(tmp);
        } else {
          tmp = newFrom;
          var = mdd_not(comp1->var);
          newFrom = bdd_compose(tmp, comp->var, var);
          mdd_free(tmp);
          mdd_free(var);
        }
        mdd_free(res);
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
      } else {
        comp1 = ImgComponentAlloc(info);
        comp1->var = mdd_dup(comp->var);
        comp1->func = res;
        if (mdd_equal(res, comp->func))
          ImgSupportCopy(info, comp1->support, comp->support);
        else
          ImgComponentGetSupport(comp1);
        array_insert_last(ImgComponent_t *, vector1, comp1);
        st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
        n++;
      }
    }
  }
  st_free_table(equivTable);

  if (constIntermediate) {
    if (!bdd_is_tautology(constIntermediate, 1)) {
      mdd_t     *tmpCofactor, *tmpAbstract;

      if (relationArray) {
        vector1 = ImgComposeConstIntermediateVars(info, vector1,
                                                  constIntermediate,
                                                  &tmpCofactor, &tmpAbstract,
                                                  NIL(mdd_t *), &newFrom);
        if (!bdd_is_tautology(tmpCofactor, 1)) {
          tmp = cofactor;
          cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpCofactor);
        if (!bdd_is_tautology(tmpAbstract, 1)) {
          tmp = abstract;
          abstract = mdd_and(tmp, tmpAbstract, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpAbstract);
        tmp = cofactor;
        cofactor = mdd_and(tmp, constIntermediate, 1, 1);
        mdd_free(tmp);
      } else {
        vector1 = ImgComposeConstIntermediateVars(info, vector1,
                                                  constIntermediate,
                                                  NIL(mdd_t *), NIL(mdd_t *),
                                                  NIL(mdd_t *), &newFrom);
      }
    }
    mdd_free(constIntermediate);
  }

  *newVector = vector1;

  if (relationArray) {
    if (newRelationArray)
      *newRelationArray = relationArray;
    if (cofactorCube && abstractCube) {
      if (cofactor) {
        if (bdd_is_tautology(cofactor, 1)) {
          mdd_free(cofactor);
          *cofactorCube = mdd_dup(c);
        } else {
          *cofactorCube = mdd_and(cofactor, c, 1, 1);
          mdd_free(cofactor);
        }
      }
      if (abstract)
        *abstractCube = abstract;
    } else {
      if (bdd_is_tautology(cofactor, 1)) {
        *newRelationArray = ImgGetCofactoredRelationArray(relationArray, c);
        mdd_free(cofactor);
      } else {
        tmp = cofactor;
        cofactor = mdd_and(tmp, c, 1, 1);
        mdd_free(tmp);
        *newRelationArray = ImgGetCofactoredRelationArray(relationArray,
                                                          cofactor);
        mdd_free(cofactor);
      }
      if (bdd_is_tautology(abstract, 1))
        mdd_free(abstract);
      else {
        tmpRelationArray = *newRelationArray;
        *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
                                                        tmpRelationArray,
                                                        abstract);
        mdd_free(abstract);
        if (tmpRelationArray != relationArray)
          mdd_array_free(tmpRelationArray);
      }
    }
  } else
    *newRelationArray = NIL(array_t);

  return(newFrom);
}

Here is the call graph for this function:

Here is the caller graph for this function:

bdd_t* ImgTfmPreImage ( ImgTfmInfo_t *  info,
bdd_t *  image 
)

AutomaticEnd Function********************************************************************

Synopsis [Computes a preimage with transition function method.]

Description [Computes a preimage with transition function method.]

SideEffects []

Definition at line 100 of file imgTfmBwd.c.

{
  bdd_t         *preImg, *pre;
  int           turnDepth;
  bdd_t         *refResult, *one;
  array_t       *relationArray;
  int           partial;
  bdd_t         *from;
  array_t       *vector;

  if (bdd_is_tautology(image, 1)) {
    preImg = mdd_one(info->manager);
    return(preImg);
  } else if (bdd_is_tautology(image, 0)) {
    preImg = mdd_zero(info->manager);
    return(preImg);
  }

  info->maxIntermediateSize = 0;
  if (info->buildTR) {
    if (info->option->preSplitMethod == 4 &&
        info->option->preSplitMaxDepth < 0 &&
        info->option->buildPartialTR == FALSE &&
        info->preKeepPiInTr == FALSE &&
        info->option->preCanonical == FALSE) {
      mdd_t *range;
      range = ImgSubstitute(image, info->functionData, Img_D2R_c);
      preImg = ImgBddLinearAndSmooth(info->manager, range,
                      info->bwdClusteredRelationArray,
                      info->bwdArraySmoothVarBddArray,
                      info->bwdSmoothVarCubeArray,
                      info->option->verbosity);
      mdd_free(range);
      return(preImg);
    }
    relationArray = mdd_array_duplicate(info->bwdClusteredRelationArray);
  } else
    relationArray = NIL(array_t);

  one = mdd_one(info->manager);

  vector = info->vector;
  from = image;

  partial = 0;
  if (info->option->preSplitMethod == 0) {
    preImg = PreImageByDomainCofactoring(info, vector, from,
                                         NIL(array_t), NIL(mdd_t), NIL(mdd_t),
                                         info->option->preSplitMethod, 0, 0);
  } else if (info->option->preSplitMethod == 1) {
    preImg = PreImageByConstraintCofactoring(info, vector, from,
                                             info->option->preSplitMethod,
                                             0, 0);
  } else if (info->option->preSplitMethod == 3) {
    preImg = PreImageBySubstitution(info, vector, from);
  } else {
    turnDepth = info->option->turnDepth;
    if (turnDepth == 0) {
      if (info->option->preSplitMethod == 2) {
        preImg = PreImageByConstraintCofactoring(info, vector, from,
                                                 info->option->preSplitMethod,
                                                 turnDepth, 0);
      } else
        preImg = ImgPreImageByHybrid(info, vector, from);
    } else if (info->option->preSplitMethod == 2) {
      preImg = PreImageByDomainCofactoring(info, vector, from,
                                           relationArray,
                                           NIL(mdd_t), NIL(mdd_t),
                                           info->option->preSplitMethod,
                                           turnDepth, 0);
    } else {
      if (info->buildTR) {
        if (info->buildTR == 2) {
          if (info->buildPartialTR) {
            preImg = PreImageByStaticDomainCofactoring(info, vector,
                                                        from, relationArray,
                                                        turnDepth, 0);
            partial = 1;
          } else {
            preImg = PreImageByStaticDomainCofactoring(info, NIL(array_t),
                                                        from, relationArray,
                                                        turnDepth, 0);
          }
        } else if (info->option->delayedSplit) {
          preImg = PreImageByDomainCofactoring(info, vector, from,
                                                relationArray, one, one,
                                                info->option->preSplitMethod,
                                                turnDepth, 0);
        } else {
          preImg = PreImageByDomainCofactoring(info, vector, from,
                                                relationArray,
                                                NIL(mdd_t), NIL(mdd_t),
                                                info->option->preSplitMethod,
                                                turnDepth, 0);
        }
      } else {
        preImg = PreImageByDomainCofactoring(info, vector, from,
                                             relationArray,
                                             NIL(mdd_t), NIL(mdd_t),
                                             info->option->preSplitMethod,
                                             turnDepth, 0);
      }
    }
  }
  mdd_free(one);

  if (info->option->debug) {
    if (info->buildTR == 2) {
      refResult = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t),
                                                        image, relationArray,
                                                        NIL(mdd_t), NIL(mdd_t));
    } else {
      if (partial) {
        refResult = ImgPreImageByHybridWithStaticSplit(info, info->vector,
                                                        image, relationArray,
                                                        NIL(mdd_t), NIL(mdd_t));
      } else
        refResult = ImgPreImageByHybrid(info, info->vector, image);
    }
    assert(mdd_equal_mod_care_set_array(refResult, preImg,
                                        info->toCareSetArray));
    mdd_free(refResult);
  }

  if (relationArray)
    mdd_array_free(relationArray);

  if (info->preCache && info->option->autoFlushCache == 1)
    ImgFlushCache(info->preCache);
  if (info->preKeepPiInTr == TRUE) {
    if (info->functionData->quantifyCube)
      pre = bdd_smooth_with_cube(preImg, info->functionData->quantifyCube);
    else
      pre = bdd_smooth(preImg, info->functionData->quantifyBddVars);
    mdd_free(preImg);
  } else
    pre = preImg;
  if (info->option->verbosity) {
    fprintf(vis_stdout,
            "** tfm info: max BDD size for intermediate product = %d\n",
            info->maxIntermediateSize);
  }
  return(pre);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bdd_t * PreImageByConstraintCofactoring ( ImgTfmInfo_t *  info,
array_t *  delta,
bdd_t *  image,
int  splitMethod,
int  turnDepth,
int  depth 
) [static]

Function********************************************************************

Synopsis [Computes preimage with constraint cofactoring method.]

Description [Computes preimage with constraint cofactoring method.]

SideEffects []

Definition at line 1248 of file imgTfmBwd.c.

{
  array_t               *newDelta, *tmpDelta, *vector;
  bdd_t                 *preImg, *preImgT, *preImgE, *imgT, *imgE;
  bdd_t                 *c, *newImg, *tmpImg;
  int                   split;
  bdd_t                 *var, *varNot, *refResult;
  ImgComponent_t        *comp;
  int                   nRecur, size;
  mdd_t                 *essentialCube;
  int                   findEssential;
  int                   foundEssentialDepth;
  int                   foundEssentialDepthT, foundEssentialDepthE;
  mdd_t                 *saveCareSet = NIL(mdd_t), *tmp;

  info->nRecursionB++;

  if (info->nIntermediateVars)
    size = ImgVectorFunctionSize(delta);
  else
    size = array_n(delta);
  if (size == 1) {
    preImg = PreImageBySubstitution(info, delta, image);
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    info->foundEssentialDepth = info->option->maxEssentialDepth;
    return(preImg);
  }

  if (info->option->findEssential) {
    if (info->option->findEssential == 1)
      findEssential = 1;
    else {
      if (depth >= info->lastFoundEssentialDepth)
        findEssential = 1;
      else
        findEssential = 0;
    }
  } else
    findEssential = 0;
  if (findEssential) {
    essentialCube = bdd_find_essential_cube(image);

    if (!bdd_is_tautology(essentialCube, 1)) {
      info->averageFoundEssential = (info->averageFoundEssential *
        (float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
        (float)(info->nFoundEssentials + 1);
      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
        (float)info->nFoundEssentials + (float)depth) /
        (float)(info->nFoundEssentials + 1);
      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
        info->topFoundEssentialDepth = depth;
      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
        info->foundEssentials[depth]++;
      info->nFoundEssentials++;
      tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
                        NIL(array_t), &tmpDelta, NIL(mdd_t *),
                        NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
      foundEssentialDepth = depth;
    } else {
      tmpDelta = delta;
      tmpImg = image;
      foundEssentialDepth = info->option->maxEssentialDepth;
    }
    mdd_free(essentialCube);
    foundEssentialDepthT = info->option->maxEssentialDepth;
    foundEssentialDepthE = info->option->maxEssentialDepth;
  } else {
    tmpDelta = delta;
    tmpImg = image;
    /* To remove compiler warnings */
    foundEssentialDepth = -1;
    foundEssentialDepthT = -1;
    foundEssentialDepthE = -1;
  }

  if (info->option->preCanonical) {
    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg, NIL(array_t),
                                &newDelta, NIL(array_t *), NIL(mdd_t *),
                                NIL(mdd_t *));
  } else {
    newImg = tmpImg;
    newDelta = tmpDelta;
  }
  if (tmpDelta != delta)
    ImgVectorFree(tmpDelta);
  if (tmpImg != image)
    mdd_free(tmpImg);

  if (bdd_is_tautology(newImg, 1) || bdd_is_tautology(newImg, 0)) {
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(newImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    ImgVectorFree(newDelta);
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(newImg);
  }

  if (info->preCache) {
    preImg = ImgCacheLookupTable(info, info->preCache, newDelta, newImg);
    if (preImg) {
      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
      if (depth > info->maxDepthB)
        info->maxDepthB = depth;
      info->nLeavesB++;
      if (info->option->debug) {
        refResult = ImgPreImageByHybrid(info, newDelta, newImg);
        tmp = refResult;
        refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
        mdd_free(tmp);
        tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
        assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                            info->toCareSetArray));
        mdd_free(refResult);
        mdd_free(tmp);
      }
      ImgVectorFree(newDelta);
      mdd_free(newImg);
      if (findEssential)
        info->foundEssentialDepth = foundEssentialDepth;
      return(preImg);
    }
  }

  if (depth == turnDepth) {
    preImg = ImgPreImageByHybrid(info, newDelta, newImg);
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    if (info->preCache)
      ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
    else {
      ImgVectorFree(newDelta);
      mdd_free(newImg);
    }
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    info->nTurnsB++;
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(preImg);
  }

  split = PreImageChooseSplitVar(info, newDelta, newImg,
                                 1, info->option->preOutputSplit);
  comp = array_fetch(ImgComponent_t *, newDelta, split);
  var = mdd_dup(comp->var);
  varNot = mdd_not(var);
  imgE = bdd_cofactor(newImg, varNot);
  mdd_free(varNot);
  imgT = bdd_cofactor(newImg, var);
  mdd_free(var);
  if (!info->preCache && !info->option->debug)
    mdd_free(newImg);
  c = PreImageDeleteOneComponent(info, newDelta, split, &vector);
  if (!info->preCache && !info->option->debug)
    ImgVectorFree(newDelta);

  nRecur = 0;
  if (bdd_is_tautology(imgT, 1))
    preImgT = mdd_one(info->manager);
  else if (bdd_is_tautology(imgT, 0))
    preImgT = mdd_zero(info->manager);
  else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, c, 1, 1);
    }
    preImgT = PreImageByConstraintCofactoring(info, vector, imgT, splitMethod,
                                                turnDepth, depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthT = info->foundEssentialDepth;
    nRecur++;
  }
  mdd_free(imgT);
  if (bdd_is_tautology(imgE, 1))
    preImgE = mdd_one(info->manager);
  else if (bdd_is_tautology(imgE, 0))
    preImgE = mdd_zero(info->manager);
  else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, c, 1, 0);
    }
    preImgE = PreImageByConstraintCofactoring(info, vector, imgE, splitMethod,
                                                turnDepth, depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthE = info->foundEssentialDepth;
    nRecur++;
  }
  mdd_free(imgE);
  ImgVectorFree(vector);
  preImg = bdd_ite(c, preImgT, preImgE, 1, 1, 1);
  if (info->option->verbosity) {
    size = bdd_size(preImg);
    if (size > info->maxIntermediateSize)
      info->maxIntermediateSize = size;
    if (info->option->printBddSize) {
      fprintf(vis_stdout, "** tfm info: bdd_ite(%d,%d,%d) = %d\n",
              bdd_size(c), bdd_size(preImgT), bdd_size(preImgE),
              bdd_size(preImg));
    }
  }
  mdd_free(c);
  mdd_free(preImgT);
  mdd_free(preImgE);

  if (info->preCache)
    ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));

  if (info->option->debug) {
    refResult = ImgPreImageByHybrid(info, newDelta, newImg);
    tmp = refResult;
    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
    mdd_free(tmp);
    tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
    assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                        info->toCareSetArray));
    mdd_free(refResult);
    mdd_free(tmp);
    if (!info->preCache) {
      ImgVectorFree(newDelta);
      mdd_free(newImg);
    }
  }

  if (nRecur == 0) {
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
  }

  if (findEssential) {
    if (foundEssentialDepth == info->option->maxEssentialDepth) {
      if (foundEssentialDepthT < foundEssentialDepthE)
        foundEssentialDepth = foundEssentialDepthT;
      else
        foundEssentialDepth = foundEssentialDepthE;
    }
    info->foundEssentialDepth = foundEssentialDepth;
  }
  return(preImg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bdd_t * PreImageByDomainCofactoring ( ImgTfmInfo_t *  info,
array_t *  delta,
bdd_t *  image,
array_t *  relationArray,
mdd_t *  cofactorCube,
mdd_t *  abstractCube,
int  splitMethod,
int  turnDepth,
int  depth 
) [static]

AutomaticStart

Function********************************************************************

Synopsis [Computes preimage with domain cofactoring method.]

Description [Computes preimage with domain cofactoring method.]

SideEffects []

Definition at line 261 of file imgTfmBwd.c.

{
  array_t       *newDelta, *tmpDelta, *vectorT, *vectorE;
  bdd_t         *preImg, *preImgT, *preImgE, *imgT, *imgE, *newImg, *tmpImg;
  int           split;
  bdd_t         *var, *varNot, *refResult;
  int           nRecur;
  array_t       *relationArrayT, *relationArrayE;
  array_t       *newRelationArray, *tmpRelationArray;
  mdd_t         *cofactorCubeT, *cofactorCubeE;
  mdd_t         *abstractCubeT, *abstractCubeE;
  mdd_t         *newCofactorCube, *newAbstractCube;
  mdd_t         *cofactor, *abstract;
  mdd_t         *essentialCube, *tmp;
  int           findEssential;
  int           foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
  int           turnFlag, size;
  mdd_t         *saveCareSet = NIL(mdd_t);

  newRelationArray = NIL(array_t);

  if (info->option->checkEquivalence && relationArray) {
    assert(ImgCheckEquivalence(info, delta, relationArray,
                                cofactorCube, abstractCube, 1));
  }

  info->nRecursionB++;
  if (info->option->debug) {
    if (relationArray) {
      refResult = ImgPreImageByHybrid(info, delta, image);
      preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), image,
                                                  relationArray,
                                                  cofactorCube, abstractCube);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = preImg;
      preImg = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      assert(mdd_equal_mod_care_set_array(refResult, preImg,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(preImg);
    }
  }

  if (info->nIntermediateVars)
    size = ImgVectorFunctionSize(delta);
  else
    size = array_n(delta);
  if (size == 1) {
    preImg = PreImageBySubstitution(info, delta, image);
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    info->foundEssentialDepth = info->option->maxEssentialDepth;
    return(preImg);
  }

  if (info->option->findEssential) {
    if (info->option->findEssential == 1)
      findEssential = 1;
    else {
      if (depth >= info->lastFoundEssentialDepth)
        findEssential = 1;
      else
        findEssential = 0;
    }
  } else
    findEssential = 0;
  if (findEssential) {
    essentialCube = bdd_find_essential_cube(image);

    if (!bdd_is_tautology(essentialCube, 1)) {
      info->averageFoundEssential = (info->averageFoundEssential *
        (float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
        (float)(info->nFoundEssentials + 1);
      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
        (float)info->nFoundEssentials + (float)depth) /
        (float)(info->nFoundEssentials + 1);
      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
        info->topFoundEssentialDepth = depth;
      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
        info->foundEssentials[depth]++;
      info->nFoundEssentials++;
      if (info->option->delayedSplit && relationArray) {
        tmpRelationArray = relationArray;
        tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
                        tmpRelationArray, &tmpDelta, NIL(mdd_t *),
                        NIL(array_t *), &cofactor, &abstract);
        if (bdd_is_tautology(cofactor, 1))
          newCofactorCube = cofactorCube;
        else
          newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
        mdd_free(cofactor);
        if (bdd_is_tautology(abstract, 1))
          newAbstractCube = abstractCube;
        else
          newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
        mdd_free(abstract);
      } else {
        if (relationArray)
          tmpRelationArray = mdd_array_duplicate(relationArray);
        else
          tmpRelationArray = relationArray;
        tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
                        tmpRelationArray, &tmpDelta, NIL(mdd_t *),
                        NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
        newCofactorCube = cofactorCube;
        newAbstractCube = abstractCube;
      }
      foundEssentialDepth = depth;
    } else {
      tmpDelta = delta;
      tmpRelationArray = relationArray;
      tmpImg = image;
      newCofactorCube = cofactorCube;
      newAbstractCube = abstractCube;
      foundEssentialDepth = info->option->maxEssentialDepth;
    }
    mdd_free(essentialCube);
    foundEssentialDepthT = info->option->maxEssentialDepth;
    foundEssentialDepthE = info->option->maxEssentialDepth;
  } else {
    tmpDelta = delta;
    tmpRelationArray = relationArray;
    tmpImg = image;
    newCofactorCube = cofactorCube;
    newAbstractCube = abstractCube;
    /* To remove compiler warnings */
    foundEssentialDepth = -1;
    foundEssentialDepthT = -1;
    foundEssentialDepthE = -1;
  }

  if (!info->option->preCanonical) {
    newImg = tmpImg;
    newDelta = tmpDelta;
    newRelationArray = tmpRelationArray;
  } else if (info->option->delayedSplit && relationArray) {
    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg,
                                        tmpRelationArray, &newDelta,
                                        &newRelationArray,
                                        &cofactor, &abstract);
    if (!bdd_is_tautology(cofactor, 1)) {
      if (newCofactorCube == cofactorCube)
        newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
      else {
        tmp = newCofactorCube;
        newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
        mdd_free(tmp);
      }
    }
    mdd_free(cofactor);
    if (!bdd_is_tautology(abstract, 1)) {
      if (newAbstractCube == abstractCube)
        newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
      else {
        tmp = newAbstractCube;
        newAbstractCube = mdd_and(tmp, abstract, 1, 1);
        mdd_free(tmp);
      }
    }
    mdd_free(abstract);
  } else {
    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg,
                                        tmpRelationArray, &newDelta,
                                        &newRelationArray,
                                        NIL(mdd_t *), NIL(mdd_t *));
  }
  if (tmpDelta != delta)
    ImgVectorFree(tmpDelta);
  if (tmpImg != image)
    mdd_free(tmpImg);
  if (tmpRelationArray && tmpRelationArray != relationArray &&
      tmpRelationArray != newRelationArray) {
    mdd_array_free(tmpRelationArray);
  }

  if (info->option->debug) {
    if (relationArray) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
                                                  newRelationArray,
                                                  newCofactorCube,
                                                  newAbstractCube);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = preImg;
      preImg = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      assert(mdd_equal_mod_care_set_array(refResult, preImg,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(preImg);
    }
  }

  if (bdd_is_tautology(newImg, 1) || bdd_is_tautology(newImg, 0)) {
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(newImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    if (newDelta != delta)
      ImgVectorFree(newDelta);
    if (relationArray && newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newCofactorCube && newCofactorCube != cofactorCube)
      mdd_free(newCofactorCube);
    if (newAbstractCube && newAbstractCube != abstractCube)
      mdd_free(newAbstractCube);
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(newImg);
  }
  if (array_n(newDelta) <= 1) {
    if (array_n(newDelta) == 0)
      preImg = newImg;
    else {
      assert(array_n(newDelta) == 1);
      preImg = PreImageBySubstitution(info, newDelta, newImg);
      mdd_free(newImg);
    }
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, delta, image);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    if (newDelta != delta)
      ImgVectorFree(newDelta);
    if (relationArray && newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newCofactorCube && newCofactorCube != cofactorCube)
      mdd_free(newCofactorCube);
    if (newAbstractCube && newAbstractCube != abstractCube)
      mdd_free(newAbstractCube);
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(preImg);
  }

  if (info->preCache) {
    preImg = ImgCacheLookupTable(info, info->preCache, newDelta, newImg);
    if (preImg) {
      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
      if (depth > info->maxDepthB)
        info->maxDepthB = depth;
      info->nLeavesB++;
      if (info->option->debug) {
        refResult = ImgPreImageByHybrid(info, newDelta, newImg);
        tmp = refResult;
        refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
        mdd_free(tmp);
        tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
        assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                            info->toCareSetArray));
        mdd_free(refResult);
        mdd_free(tmp);
      }
      if (newDelta != delta)
        ImgVectorFree(newDelta);
      if (newImg != image)
        mdd_free(newImg);
      if (relationArray && newRelationArray != relationArray)
        mdd_array_free(newRelationArray);
      if (newCofactorCube && newCofactorCube != cofactorCube)
        mdd_free(newCofactorCube);
      if (newAbstractCube && newAbstractCube != abstractCube)
        mdd_free(newAbstractCube);
      if (findEssential)
        info->foundEssentialDepth = foundEssentialDepth;
      return(preImg);
    }
  }

  turnFlag = 0;
  if (splitMethod == 4 && turnDepth == -1) {
    if (depth < info->option->preSplitMinDepth) {
      info->nSplitsB++;
      turnFlag = 0;
    } else if (depth > info->option->preSplitMaxDepth) {
      info->nConjoinsB++;
      turnFlag = 1;
    } else {
      turnFlag = ImgDecideSplitOrConjoin(info, newDelta, newImg, 1,
                                         newRelationArray, newCofactorCube,
                                         newAbstractCube, 0, depth);
    }
  } else {
    if (depth == turnDepth)
      turnFlag = 1;
    else
      turnFlag = 0;
  }
  if (turnFlag) {
    if (splitMethod == 2) {
      preImg = PreImageByConstraintCofactoring(info, newDelta, newImg,
                                                info->option->preSplitMethod,
                                                0, depth + 1);
    } else {
      if (relationArray) {
        preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
                                                    newRelationArray,
                                                    newCofactorCube,
                                                    newAbstractCube);
      } else
        preImg = ImgPreImageByHybrid(info, newDelta, newImg);
    }
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    if (splitMethod == 4) {
      if (info->preCache)
        ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
      else {
        if (newDelta != delta)
          ImgVectorFree(newDelta);
        if (newImg != image)
          mdd_free(newImg);
      }
      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                              (float)depth) / (float)(info->nLeavesB + 1);
      if (depth > info->maxDepthB)
        info->maxDepthB = depth;
      info->nLeavesB++;
    } else {
      if (newDelta != delta)
        ImgVectorFree(newDelta);
      if (newImg != image)
        mdd_free(newImg);
    }
    if (relationArray && newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newCofactorCube && newCofactorCube != cofactorCube)
      mdd_free(newCofactorCube);
    if (newAbstractCube && newAbstractCube != abstractCube)
      mdd_free(newAbstractCube);
    info->nTurnsB++;
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(preImg);
  }

  split = PreImageChooseSplitVar(info, newDelta, newImg,
                                 0, info->option->preInputSplit);

  /* No more present state variable to split */
  if (split == -1) {
    if (info->option->preDcLeafMethod == 0 ||
        info->option->preDcLeafMethod == 2) {
      if (info->option->preDcLeafMethod == 0)
        preImg = PreImageBySubstitution(info, newDelta, newImg);
      else if (relationArray) {
        preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
                                                    newRelationArray,
                                                    newCofactorCube,
                                                    newAbstractCube);
      } else
        preImg = ImgPreImageByHybrid(info, newDelta, newImg);
      if (info->preCache)
        ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
      if (depth > info->maxDepthB)
        info->maxDepthB = depth;
      info->nLeavesB++;
    } else {
      preImg = PreImageByConstraintCofactoring(info, newDelta, newImg,
                                            splitMethod, turnDepth,
                                            depth + 1);
      info->nRecursionB--;
    }
    if (splitMethod == 0)
      info->nTurnsB++;
    if (info->option->debug) {
      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
      tmp = refResult;
      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
      mdd_free(tmp);
      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
      assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                          info->toCareSetArray));
      mdd_free(refResult);
      mdd_free(tmp);
    }
    if (info->option->preDcLeafMethod != 0 || !info->preCache) {
      if (newDelta != delta)
        ImgVectorFree(newDelta);
      if (newImg != image)
        mdd_free(newImg);
    }
    if (relationArray && newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newCofactorCube && newCofactorCube != cofactorCube)
      mdd_free(newCofactorCube);
    if (newAbstractCube && newAbstractCube != abstractCube)
      mdd_free(newAbstractCube);
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(preImg);
  }

  var = bdd_var_with_index(info->manager, split);
  varNot = mdd_not(var);
  if (info->option->delayedSplit && relationArray) {
    imgT = DomainCofactoring(info, newDelta, newImg, newRelationArray, var,
                             &vectorT, &relationArrayT, &cofactor, &abstract);
    if (bdd_is_tautology(cofactor, 1))
      cofactorCubeT = newCofactorCube;
    else
      cofactorCubeT = mdd_and(newCofactorCube, cofactor, 1, 1);
    mdd_free(cofactor);
    if (bdd_is_tautology(abstract, 1))
      abstractCubeT = newAbstractCube;
    else
      abstractCubeT = mdd_and(newAbstractCube, abstract, 1, 1);
    mdd_free(abstract);

    imgE = DomainCofactoring(info, newDelta, newImg, newRelationArray, varNot,
                             &vectorE, &relationArrayE, &cofactor, &abstract);
    if (bdd_is_tautology(cofactor, 1))
      cofactorCubeE = newCofactorCube;
    else
      cofactorCubeE = mdd_and(newCofactorCube, cofactor, 1, 1);
    mdd_free(cofactor);
    if (bdd_is_tautology(abstract, 1))
      abstractCubeE = newAbstractCube;
    else
      abstractCubeE = mdd_and(newAbstractCube, abstract, 1, 1);
    mdd_free(abstract);
  } else {
    imgT = DomainCofactoring(info, newDelta, newImg, newRelationArray, var,
                             &vectorT, &relationArrayT,
                             NIL(mdd_t *), NIL(mdd_t *));
    cofactorCubeT = NIL(mdd_t);
    abstractCubeT = NIL(mdd_t);

    imgE = DomainCofactoring(info, newDelta, newImg, newRelationArray, varNot,
                             &vectorE, &relationArrayE,
                             NIL(mdd_t *), NIL(mdd_t *));
    cofactorCubeE = NIL(mdd_t);
    abstractCubeE = NIL(mdd_t);
  }
  if (relationArray && newRelationArray != relationArray)
    mdd_array_free(newRelationArray);
  mdd_free(varNot);

  if (!info->preCache && !info->option->debug) {
    if (newDelta != delta)
      ImgVectorFree(newDelta);
    if (newImg != image)
      mdd_free(newImg);
  }

  nRecur = 0;
  if (bdd_is_tautology(imgT, 1))
    preImgT = mdd_one(info->manager);
  else if (bdd_is_tautology(imgT, 0))
    preImgT = mdd_zero(info->manager);
  else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, var, 1, 1);
    }
    preImgT = PreImageByDomainCofactoring(info, vectorT, imgT, relationArrayT,
                                          cofactorCubeT, abstractCubeT,
                                          splitMethod, turnDepth,
                                          depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthT = info->foundEssentialDepth;
    nRecur++;
  }
  ImgVectorFree(vectorT);
  mdd_free(imgT);
  if (relationArrayT && relationArrayT != newRelationArray)
    mdd_array_free(relationArrayT);
  if (cofactorCubeT && cofactorCubeT != newCofactorCube)
    mdd_free(cofactorCubeT);
  if (abstractCubeT && abstractCubeT != newAbstractCube)
    mdd_free(abstractCubeT);

  if (bdd_is_tautology(imgE, 1))
    preImgE = mdd_one(info->manager);
  else if (bdd_is_tautology(imgE, 0))
    preImgE = mdd_zero(info->manager);
  else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, var, 1, 0);
    }
    preImgE = PreImageByDomainCofactoring(info, vectorE, imgE, relationArrayE,
                                          cofactorCubeE, abstractCubeE,
                                          splitMethod, turnDepth,
                                          depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthE = info->foundEssentialDepth;
    nRecur++;
  }
  ImgVectorFree(vectorE);
  mdd_free(imgE);
  if (relationArrayE && relationArrayT != newRelationArray)
    mdd_array_free(relationArrayE);
  if (cofactorCubeE && cofactorCubeE != newCofactorCube)
    mdd_free(cofactorCubeE);
  if (abstractCubeE && abstractCubeE != newAbstractCube)
    mdd_free(abstractCubeE);
  if (newCofactorCube && newCofactorCube != cofactorCube)
    mdd_free(newCofactorCube);
  if (newAbstractCube && newAbstractCube != abstractCube)
    mdd_free(newAbstractCube);

  preImg = bdd_ite(var, preImgT, preImgE, 1, 1, 1);
  if (info->option->verbosity) {
    size = bdd_size(preImg);
    if (size > info->maxIntermediateSize)
      info->maxIntermediateSize = size;
    if (info->option->printBddSize) {
      fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
              bdd_size(preImgT), bdd_size(preImgE), bdd_size(preImg));
    }
  }
  mdd_free(var);
  mdd_free(preImgE);
  mdd_free(preImgT);

  if (info->preCache)
    ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));

  if (info->option->debug) {
    refResult = ImgPreImageByHybrid(info, newDelta, newImg);
    tmp = refResult;
    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
    mdd_free(tmp);
    tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
    assert(mdd_equal_mod_care_set_array(refResult, tmp,
                                        info->toCareSetArray));
    mdd_free(refResult);
    mdd_free(tmp);
    if (!info->preCache) {
      if (newDelta != delta)
        ImgVectorFree(newDelta);
      if (newImg != image)
        mdd_free(newImg);
    }
  }

  if (nRecur == 0) {
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                                (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
  }

  if (findEssential) {
    if (foundEssentialDepth == info->option->maxEssentialDepth) {
      if (foundEssentialDepthT < foundEssentialDepthE)
        foundEssentialDepth = foundEssentialDepthT;
      else
        foundEssentialDepth = foundEssentialDepthE;
    }
    info->foundEssentialDepth = foundEssentialDepth;
  }
  return(preImg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static mdd_t * PreImageByStaticDomainCofactoring ( ImgTfmInfo_t *  info,
array_t *  vector,
mdd_t *  from,
array_t *  relationArray,
int  turnDepth,
int  depth 
) [static]

Function********************************************************************

Synopsis [Computes a preimage by static input splitting.]

Description [Computes a preimage by static input splitting.]

SideEffects []

Definition at line 884 of file imgTfmBwd.c.

{
  array_t       *vectorT, *vectorE, *newVector;
  mdd_t         *resT, *resE, *res, *cubeT, *cubeE;
  mdd_t         *fromT, *fromE, *newFrom, *tmpFrom;
  mdd_t         *var, *varNot;
  array_t       *relationArrayT, *relationArrayE;
  array_t       *newRelationArray, *tmpRelationArray;
  int           nRecur;
  mdd_t         *essentialCube, *refResult;
  int           findEssential;
  int           foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
  int           turnFlag, size;
  mdd_t         *saveCareSet = NIL(mdd_t), *tmp;

  info->nRecursionB++;

  turnFlag = 0;
  if (turnDepth == -1) {
    if (depth < info->option->preSplitMinDepth) {
      info->nSplitsB++;
      turnFlag = 0;
    } else if (depth > info->option->preSplitMaxDepth) {
      info->nConjoinsB++;
      turnFlag = 1;
    } else {
      turnFlag = ImgDecideSplitOrConjoin(info, vector, from, 1,
                                         relationArray, NIL(mdd_t),
                                         NIL(mdd_t), 1, depth);
    }
  } else {
    if (depth == turnDepth)
      turnFlag = 1;
    else
      turnFlag = 0;
  }
  if (turnFlag) {
    res = ImgPreImageByHybridWithStaticSplit(info, vector, from, relationArray,
                                             NIL(mdd_t), NIL(mdd_t));
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                          (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    info->foundEssentialDepth = info->option->maxEssentialDepth;
    return(res);
  }

  if (info->option->findEssential) {
    if (info->option->findEssential == 1)
      findEssential = 1;
    else {
      if (depth >= info->lastFoundEssentialDepth)
        findEssential = 1;
      else
        findEssential = 0;
    }
  } else
    findEssential = 0;
  if (findEssential) {
    essentialCube = bdd_find_essential_cube(from);

    if (!bdd_is_tautology(essentialCube, 1)) {
      info->averageFoundEssential = (info->averageFoundEssential *
        (float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
        (float)(info->nFoundEssentials + 1);
      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
        (float)info->nFoundEssentials + (float)depth) /
        (float)(info->nFoundEssentials + 1);
      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
        info->topFoundEssentialDepth = depth;
      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
        info->foundEssentials[depth]++;
      info->nFoundEssentials++;
      if (vector) {
        array_t *tmpVector;
        if (info->option->preCanonical) {
          tmpFrom = PreImageMakeRelationCanonical(info, vector, from,
                                                relationArray, &newVector,
                                                &newRelationArray);
        } else {
          tmpFrom = from;
          newVector = vector;
          newRelationArray = relationArray;
        }
        tmpVector = newVector;
        newFrom = ImgVectorMinimize(info, tmpVector, essentialCube, tmpFrom,
                        newRelationArray, &newVector, NIL(mdd_t *),
                        NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
        if (tmpVector != vector)
          ImgVectorFree(tmpVector);
        if (tmpFrom != from)
          mdd_free(tmpFrom);
      } else {
        tmpRelationArray = ImgGetCofactoredRelationArray(relationArray,
                                                         essentialCube);
        if (info->option->preCanonical) {
          newFrom = PreImageMakeRelationCanonical(info, vector, from,
                                                tmpRelationArray, &newVector,
                                                &newRelationArray);
          mdd_array_free(tmpRelationArray);
        } else {
          newFrom = from;
          newVector = vector;
          newRelationArray = tmpRelationArray;
        }
      }
      foundEssentialDepth = depth;
    } else {
      if (info->option->preCanonical) {
        newFrom = PreImageMakeRelationCanonical(info, vector, from,
                                                relationArray,
                                                &newVector, &newRelationArray);
      } else {
        newFrom = from;
        newVector = vector;
        newRelationArray = relationArray;
      }
      foundEssentialDepth = info->option->maxEssentialDepth;
    }
    mdd_free(essentialCube);
    foundEssentialDepthT = info->option->maxEssentialDepth;
    foundEssentialDepthE = info->option->maxEssentialDepth;
  } else {
    if (info->option->preCanonical) {
      newFrom = PreImageMakeRelationCanonical(info, vector, from, relationArray,
                                            &newVector, &newRelationArray);
    } else {
      newFrom = from;
      newVector = vector;
      newRelationArray = relationArray;
    }
    /* To remove compiler warnings */
    foundEssentialDepth = -1;
    foundEssentialDepthT = -1;
    foundEssentialDepthE = -1;
  }

  if (info->option->debug) {
    refResult = ImgPreImageByHybridWithStaticSplit(info, vector, from,
                                                   relationArray,
                                                   NIL(mdd_t), NIL(mdd_t));
    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
                                                   newRelationArray,
                                                   NIL(mdd_t), NIL(mdd_t));
    tmp = refResult;
    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
    mdd_free(tmp);
    tmp = res;
    res = mdd_and(tmp, info->debugCareSet, 1, 1);
    mdd_free(tmp);
    assert(mdd_equal_mod_care_set_array(refResult, res, info->toCareSetArray));
    mdd_free(refResult);
    mdd_free(res);
  }

  if (bdd_is_tautology(newFrom, 1)) {
    if (newVector && newVector != vector)
      ImgVectorFree(newVector);
    if (newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newFrom != from)
      mdd_free(newFrom);
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                          (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(mdd_one(info->manager));
  }

  if (depth == turnDepth ||
      (info->option->splitCubeFunc && bdd_is_cube(newFrom))) {
    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
                                             newRelationArray,
                                             NIL(mdd_t), NIL(mdd_t));
    if (newVector && newVector != vector)
      ImgVectorFree(newVector);
    if (newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newFrom != from)
      mdd_free(newFrom);
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                          (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(res);
  }

  var = ImgChooseTrSplitVar(info, newVector, newRelationArray,
                            info->option->trSplitMethod, 0);
  if (!var) {
    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
                                                   newRelationArray,
                                                   NIL(mdd_t), NIL(mdd_t));
    if (newVector && newVector != vector)
      ImgVectorFree(newVector);
    if (newRelationArray != relationArray)
      mdd_array_free(newRelationArray);
    if (newFrom != from)
      mdd_free(newFrom);
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                          (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
    if (findEssential)
      info->foundEssentialDepth = foundEssentialDepth;
    return(res);
  }

  varNot = mdd_not(var);

  nRecur = 0;
  if (newVector) {
    ImgVectorConstrain(info, newVector, var, NIL(array_t),
                        &vectorT, &cubeT, NIL(array_t *),
                        NIL(mdd_t *), NIL(mdd_t *), TRUE);
    fromT = bdd_cofactor(newFrom, cubeT);
    mdd_free(cubeT);
  } else {
    vectorT = NIL(array_t);
    fromT = mdd_dup(newFrom);
  }
  relationArrayT = ImgGetCofactoredRelationArray(newRelationArray, var);
  if (bdd_is_tautology(fromT, 1)) {
    resT = mdd_one(info->manager);
    if (vectorT)
      ImgVectorFree(vectorT);
  } else if (bdd_is_tautology(fromT, 0)) {
    resT = mdd_zero(info->manager);
    if (vectorT)
      ImgVectorFree(vectorT);
  } else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, var, 1, 1);
    }
    resT = PreImageByStaticDomainCofactoring(info, vectorT, fromT,
                             relationArrayT, turnDepth, depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthE = info->foundEssentialDepth;
    if (vectorT)
      ImgVectorFree(vectorT);
    nRecur++;
  }
  mdd_free(fromT);
  mdd_array_free(relationArrayT);

  if (newVector) {
    ImgVectorConstrain(info, newVector, varNot, NIL(array_t),
                        &vectorE, &cubeE, NIL(array_t *),
                        NIL(mdd_t *), NIL(mdd_t *), TRUE);
    if (newVector != vector)
      ImgVectorFree(newVector);
    fromE = bdd_cofactor(newFrom, cubeE);
    mdd_free(cubeE);
  } else {
    vectorE = NIL(array_t);
    fromE = mdd_dup(newFrom);
  }
  if (newFrom != from)
    mdd_free(newFrom);
  relationArrayE = ImgGetCofactoredRelationArray(newRelationArray, varNot);
  if (newRelationArray != relationArray)
    mdd_array_free(newRelationArray);
  if (bdd_is_tautology(fromE, 1)) {
    resE = mdd_one(info->manager);
    if (vectorE)
      ImgVectorFree(vectorE);
  } else if (bdd_is_tautology(fromE, 0)) {
    resE = mdd_zero(info->manager);
    if (vectorE)
      ImgVectorFree(vectorE);
  } else {
    if (info->option->debug) {
      saveCareSet = info->debugCareSet;
      info->debugCareSet = mdd_and(saveCareSet, var, 1, 0);
    }
    resE = PreImageByStaticDomainCofactoring(info, vectorE, fromE,
                             relationArrayE, turnDepth, depth + 1);
    if (info->option->debug) {
      mdd_free(info->debugCareSet);
      info->debugCareSet = saveCareSet;
    }
    if (findEssential)
      foundEssentialDepthE = info->foundEssentialDepth;
    if (vectorE)
      ImgVectorFree(vectorE);
    nRecur++;
  }
  mdd_free(fromE);
  mdd_array_free(relationArrayE);
  
  res = bdd_ite(var, resT, resE, 1, 1, 1);
  if (info->option->verbosity) {
    size = bdd_size(res);
    if (size > info->maxIntermediateSize)
      info->maxIntermediateSize = size;
    if (info->option->printBddSize) {
      fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
              bdd_size(resT), bdd_size(resE), bdd_size(res));
    }
  }
  mdd_free(resT);
  mdd_free(resE);
  mdd_free(var);
  mdd_free(varNot);

  if (info->option->debug) {
    refResult = ImgPreImageByHybridWithStaticSplit(info, vector, from,
                                                   relationArray,
                                                   NIL(mdd_t), NIL(mdd_t));
    tmp = refResult;
    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
    mdd_free(tmp);
    tmp = mdd_and(res, info->debugCareSet, 1, 1);
    assert(mdd_equal_mod_care_set_array(refResult, tmp, info->toCareSetArray));
    mdd_free(refResult);
    mdd_free(tmp);
  }

  if (nRecur == 0) {
    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
                          (float)depth) / (float)(info->nLeavesB + 1);
    if (depth > info->maxDepthB)
      info->maxDepthB = depth;
    info->nLeavesB++;
  }

  if (findEssential) {
    if (foundEssentialDepth == info->option->maxEssentialDepth) {
      if (foundEssentialDepthT < foundEssentialDepthE)
        foundEssentialDepth = foundEssentialDepthT;
      else
        foundEssentialDepth = foundEssentialDepthE;
    }
    info->foundEssentialDepth = foundEssentialDepth;
  }
  return(res);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static mdd_t * PreImageBySubstitution ( ImgTfmInfo_t *  info,
array_t *  vector,
mdd_t *  from 
) [static]

Function********************************************************************

Synopsis [Computes a preimage by Filkorn's substitution.]

Description [Computes a preimage by Filkorn's substitution.]

SideEffects []

Definition at line 1544 of file imgTfmBwd.c.

{
  int                   i, index;
  ImgComponent_t        *comp, *fromComp;
  array_t               *varArray, *funcArray;
  mdd_t                 *result;

  if (bdd_is_tautology(from, 1))
    return(mdd_one(info->manager));
  else if (bdd_is_tautology(from, 0))
    return(mdd_zero(info->manager));

  fromComp = ImgComponentAlloc(info);
  fromComp->func = from;
  ImgComponentGetSupport(fromComp);

  varArray = array_alloc(mdd_t *, 0);
  funcArray = array_alloc(mdd_t *, 0);

  for (i = 0; i < array_n(vector); i++) {
    comp = array_fetch(ImgComponent_t *, vector, i);
    index = bdd_top_var_id(comp->var);
    if (fromComp->support[index] || comp->intermediate) {
      array_insert_last(mdd_t *, varArray, comp->var);
      array_insert_last(mdd_t *, funcArray, comp->func);
    }
  }

  fromComp->func = NIL(mdd_t);
  ImgComponentFree(fromComp);

  result = bdd_vector_compose(from, varArray, funcArray);
  array_free(varArray);
  array_free(funcArray);

  /* quantify all primary inputs */
  if (info->preKeepPiInTr == FALSE) {
    array_t *quantifyVarBddArray;
    mdd_t *tmp;

    if (info->newQuantifyBddVars)
      quantifyVarBddArray = info->newQuantifyBddVars;
    else
      quantifyVarBddArray = info->quantifyVarBddArray;

    tmp = result;
    result = bdd_smooth(tmp, quantifyVarBddArray);
    mdd_free(tmp);
  }

  return(result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int PreImageChooseSplitVar ( ImgTfmInfo_t *  info,
array_t *  delta,
bdd_t *  img,
int  splitMethod,
int  split 
) [static]

Function********************************************************************

Synopsis [Chooses a splitting variable for preimage.]

Description [Chooses a splitting variable for preimage.]

SideEffects []

Definition at line 2192 of file imgTfmBwd.c.

{
  ImgComponent_t        *comp, *imgComp;
  int                   i, j, bestCost, newCost;
  int                   index, bestVar, bestComp;
  int                   nFuncs, nVars, bestOccur = 0;
  int                   *varOccur, *varCost;
  mdd_t                 *var, *varNot, *pcFunc, *ncFunc;
  int                   tieCount = 0;

  assert(array_n(delta) > 0);

  if (splitMethod == 0) {
    bestVar = -1;
    bestComp = -1;
    nFuncs = array_n(delta);
    nVars = info->nVars;
    varOccur = ALLOC(int, nVars);
    memset(varOccur, 0, sizeof(int) * nVars);
    varCost = NIL(int);
    for (i = 0; i < nFuncs; i++) {
      comp = array_fetch(ImgComponent_t *, delta, i);
      for (j = 0; j < nVars; j++) {
        if (comp->support[j])
          varOccur[j]++;
      }
    }
    switch (split) {
    case 0: /* largest support */
      for (i = 0; i < nVars; i++) {
        if (varOccur[i] == 0)
          continue;
        if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
          continue;
        if (info->intermediateVarsTable &&
            st_lookup(info->intermediateVarsTable, (char *)(long)i,
                        NIL(char *))) {
          continue;
        }
        if (bestVar == -1 || varOccur[i] > bestOccur) {
          bestVar = i;
          bestOccur = varOccur[i];
          tieCount = 1;
        } else if (varOccur[i] == bestOccur) {
          tieCount++;
          if (info->option->tieBreakMode == 0 &&
              bdd_get_level_from_id(info->manager, i) <
              bdd_get_level_from_id(info->manager, bestVar)) {
            bestVar = i;
          }
        }
      }

      if (info->option->tieBreakMode == 1 && tieCount > 1) {
        bestCost = IMG_TF_MAX_INT;
        for (i = bestVar; i < nVars; i++) {
          if (varOccur[i] != bestOccur)
            continue;
          if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
            continue;
          if (info->intermediateVarsTable &&
              st_lookup(info->intermediateVarsTable, (char *)(long)i,
                        NIL(char *))) {
            continue;
          }
          var = bdd_var_with_index(info->manager, i);
          newCost = 0;
          for (j = 0; j < array_n(delta); j++) {
            comp = array_fetch(ImgComponent_t *, delta, j);
            newCost += bdd_estimate_cofactor(comp->func, var, 1);
            newCost += bdd_estimate_cofactor(comp->func, var, 0);
          }
          mdd_free(var);

          if (newCost < bestCost) {
            bestVar = i;
            bestCost = newCost;
          } else if (newCost == bestCost) {
            if (bdd_get_level_from_id(info->manager, i) <
                bdd_get_level_from_id(info->manager, bestVar)) {
              bestVar = i;
            }
          }
        }
      }
      break;
    case 1: /* smallest support after splitting */
      /* Find the variable which makes the smallest support after splitting */
      bestCost = IMG_TF_MAX_INT;
      varCost = ALLOC(int, nVars);
      memset(varCost, 0, sizeof(int) * nVars);
      for (i = 0; i < nVars; i++) {
        if (varOccur[i] == 0)
          continue;
        if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
          continue;
        if (info->intermediateVarsTable &&
            st_lookup(info->intermediateVarsTable, (char *)(long)i,
                        NIL(char *))) {
          continue;
        }
        var = bdd_var_with_index(info->manager, i);
        varNot = mdd_not(var);
        for (j = 0; j < array_n(delta); j++) {
          comp = array_fetch(ImgComponent_t *, delta, j);
          pcFunc = bdd_cofactor(comp->func, var);
          varCost[i] += ImgCountBddSupports(pcFunc);
          mdd_free(pcFunc);
          ncFunc = bdd_cofactor(comp->func, varNot);
          varCost[i] += ImgCountBddSupports(ncFunc);
          mdd_free(ncFunc);
        }
        mdd_free(var);
        mdd_free(varNot);

        if (varCost[i] < bestCost) {
          bestCost = varCost[i];
          bestVar = i;
        } else if (varCost[i] == bestCost) {
          if (varOccur[i] < varOccur[bestVar]) {
            bestVar = i;
          } else if (varOccur[i] == varOccur[bestVar]) {
            if (bdd_get_level_from_id(info->manager, i) <
                bdd_get_level_from_id(info->manager, bestVar)) {
              bestVar = i;
            }
          }
        }
      }
      break;
    case 2: /* smallest BDD size after splitting */
      /* Find the variable which makes the smallest BDDs of all functions
         after splitting */
      bestCost = IMG_TF_MAX_INT;
      varCost = ALLOC(int, nVars);
      memset(varCost, 0, sizeof(int) * nVars);
      for (i = 0; i < nVars; i++) {
        if (varOccur[i] == 0)
          continue;
        if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
          continue;
        if (info->intermediateVarsTable &&
            st_lookup(info->intermediateVarsTable, (char *)(long)i,
                        NIL(char *))) {
          continue;
        }
        var = bdd_var_with_index(info->manager, i);
        for (j = 0; j < array_n(delta); j++) {
          comp = array_fetch(ImgComponent_t *, delta, j);
          varCost[i] += bdd_estimate_cofactor(comp->func, var, 1);
          varCost[i] += bdd_estimate_cofactor(comp->func, var, 0);
        }
        mdd_free(var);

        if (varCost[i] < bestCost) {
          bestCost = varCost[i];
          bestVar = i;
        } else if (varCost[i] == bestCost) {
          if (varOccur[i] < varOccur[bestVar]) {
            bestVar = i;
          } else if (varOccur[i] == varOccur[bestVar]) {
            if (bdd_get_level_from_id(info->manager, i) <
                bdd_get_level_from_id(info->manager, bestVar)) {
              bestVar = i;
            }
          }
        }
      }
      break;
    case 3: /* top variable */
    default:
      for (i = 0; i < nVars; i++) {
        if (varOccur[i] == 0)
          continue;
        if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
          continue;
        if (info->intermediateVarsTable &&
            st_lookup(info->intermediateVarsTable, (char *)(long)i,
                        NIL(char *))) {
          continue;
        }
        if (bestVar == -1)
          bestVar = i;
        else if (bdd_get_level_from_id(info->manager, i) <
                 bdd_get_level_from_id(info->manager, bestVar)) {
          bestVar = i;
        }
      }
    }
    FREE(varOccur);
    if (varCost)
      FREE(varCost);
  } else {
    bestComp = -1;
    bestVar = -1;
    switch (split) {
    case 0: /* smallest BDD size */
      bestCost = IMG_TF_MAX_INT;
      imgComp = ImgComponentAlloc(info);
      imgComp->func = img;
      ImgComponentGetSupport(imgComp);
      for (i = 0; i < array_n(delta); i++) {
        comp = array_fetch(ImgComponent_t *, delta, i);
        if (comp->intermediate)
          continue;
        index = (int)bdd_top_var_id(comp->var);
        if (imgComp->support[index]) {
          newCost = bdd_size(comp->func);
          if (newCost < bestCost) {
            bestComp = i;
            bestCost = newCost;
          }
        }
      }
      imgComp->func = NIL(mdd_t);
      ImgComponentFree(imgComp);
      break;
    case 1: /* largest BDD size */
      bestCost = 0;
      imgComp = ImgComponentAlloc(info);
      imgComp->func = img;
      ImgComponentGetSupport(imgComp);
      for (i = 0; i < array_n(delta); i++) {
        comp = array_fetch(ImgComponent_t *, delta, i);
        if (comp->intermediate)
          continue;
        index = (int)bdd_top_var_id(comp->var);
        if (imgComp->support[index]) {
          newCost = bdd_size(comp->func);
          if (newCost > bestCost) {
            bestComp = i;
            bestCost = newCost;
          }
        }
      }
      imgComp->func = NIL(mdd_t);
      ImgComponentFree(imgComp);
      break;
    case 2: /* top variable */
    default:
      for (i = 0; i < array_n(delta); i++) {
        comp = array_fetch(ImgComponent_t *, delta, i);
        if (comp->intermediate)
          continue;
        index = (int)bdd_top_var_id(comp->var);
        if (bestComp == -1 ||
            bdd_get_level_from_id(info->manager, index) <
            bdd_get_level_from_id(info->manager, bestVar)) {
          bestVar = index;
          bestComp = i;
        }
      }
      break;
    }
    assert(bestComp != -1);
  }

  if (splitMethod == 0)
    return(bestVar);
  else
    return(bestComp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bdd_t * PreImageDeleteOneComponent ( ImgTfmInfo_t *  info,
array_t *  delta,
int  index,
array_t **  newDelta 
) [static]

Function********************************************************************

Synopsis [Deletes a component in a vector.]

Description [Deletes a component in a vector. Deletes index-th component out of delta and copy it into newDelta.]

SideEffects []

Definition at line 2145 of file imgTfmBwd.c.

{
  int                   i;
  ImgComponent_t        *comp, *tmpComp;
  bdd_t                 *func, *newFunc;
  int                   preMinimize = info->option->preMinimize;

  assert(array_n(delta) > 0);

  comp = array_fetch(ImgComponent_t *, delta, index);
  func = mdd_dup(comp->func);

  *newDelta = array_alloc(ImgComponent_t *, 0);
  for (i = 0; i < array_n(delta); i++) {
    if (i != index) {
      comp = array_fetch(ImgComponent_t *, delta, i);
      tmpComp = ImgComponentCopy(info, comp);
      if (preMinimize) {
        newFunc = bdd_minimize(tmpComp->func, func);
        if (mdd_equal(newFunc, tmpComp->func))
          mdd_free(newFunc);
        else {
          mdd_free(tmpComp->func);
          tmpComp->func = newFunc;
          ImgSupportClear(info, tmpComp->support);
          ImgComponentGetSupport(tmpComp);
        }
      }
      array_insert_last(ImgComponent_t *, (*newDelta), tmpComp);
    }
  }

  return(func);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bdd_t * PreImageMakeRelationCanonical ( ImgTfmInfo_t *  info,
array_t *  vector,
bdd_t *  image,
array_t *  relationArray,
array_t **  newVector,
array_t **  newRelationArray 
) [static]

Function********************************************************************

Synopsis [Makes transition relation canonical for preimage.]

Description [Makes transition relation canonical for preimage. Quantifies out the next state variables that do not occur in the image, and when a vector exists, delete the components which do not appear in the image. If a component is constant, simplify the image with the constant value and delete the corresponding component from delta Side effect on delta. Return new image.]

SideEffects []

Definition at line 1863 of file imgTfmBwd.c.

{
  array_t               *tmpVector, *cofactoredVector;
  bdd_t                 *simple, *tmp, *newImage;
  ImgComponent_t        *comp, *comp1, *imgComp;
  int                   i, j, id;
  mdd_t                 *cofactor, *abstract, *var, *nsVar;
  array_t               *tmpRelationArray;
  int                   changed = 0;
  mdd_t                 *yVarsCube, *rangeCube, *relation, *tmp2;
  array_t               *supportIds;

  imgComp = ImgComponentAlloc(info);
  imgComp->func = image;
  ImgComponentGetSupport(imgComp);

  if (vector) {
    newImage = mdd_dup(image);
    cofactor = mdd_one(info->manager);
    abstract = mdd_one(info->manager);

    if (info->nIntermediateVars) {
      mdd_t     *tmpCofactor, *tmpAbstract;
      mdd_t     *constIntermediate;

      if (ImgExistConstIntermediateVar(vector)) {
        constIntermediate = mdd_one(info->manager);

        for (i = 0; i < array_n(vector); i++) {
          comp = array_fetch(ImgComponent_t *, vector, i);
          if (comp->intermediate) {
            if (mdd_is_tautology(comp->func, 1)) {
              tmp = constIntermediate;
              constIntermediate = mdd_and(tmp, comp->var, 1, 1);
              mdd_free(tmp);
            } else if (mdd_is_tautology(comp->func, 0)) {
              tmp = constIntermediate;
              constIntermediate = mdd_and(tmp, comp->var, 1, 0);
              mdd_free(tmp);
            }
          }
        }

        cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
                                                           constIntermediate,
                                                           &tmpCofactor,
                                                           &tmpAbstract,
                                                           NIL(mdd_t *),
                                                           &newImage);

        if (!bdd_is_tautology(tmpCofactor, 1)) {
          tmp = cofactor;
          cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpCofactor);
        if (!bdd_is_tautology(tmpAbstract, 1)) {
          tmp = abstract;
          abstract = mdd_and(tmp, tmpAbstract, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpAbstract);
        mdd_free(constIntermediate);
      } else
        cofactoredVector = vector;
    } else
      cofactoredVector = vector;

    /* Simplify image -- canonicalize vector */
    tmpVector = array_alloc(ImgComponent_t *, 0);
    for (i = 0; i < array_n(cofactoredVector); i++) {
      comp = array_fetch(ImgComponent_t *, cofactoredVector, i);
      if (comp->intermediate) {
        comp1 = ImgComponentCopy(info, comp);
        array_insert_last(ImgComponent_t *, tmpVector, comp1);
        continue;
      }
      id = (int)bdd_top_var_id(comp->var);
      if (!imgComp->support[id]) {
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
        continue;
      }
      if (mdd_is_tautology(comp->func, 1)) {
        changed = 1;
        simple = bdd_cofactor(newImage, comp->var);
        mdd_free(newImage);
        newImage = simple;
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
      } else if (mdd_is_tautology(comp->func, 0)) {
        changed = 1;
        tmp = mdd_not(comp->var);
        simple = bdd_cofactor(newImage, tmp);
        mdd_free(tmp);
        mdd_free(newImage);
        newImage = simple;
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
      } else {
        comp1 = ImgComponentCopy(info, comp);
        array_insert_last(ImgComponent_t *, tmpVector, comp1);
      }
    }
    if (cofactoredVector && cofactoredVector != vector)
      ImgVectorFree(cofactoredVector);

    if (changed) {
      /* Now Simplify delta by deleting the non-affecting components */
      *newVector = array_alloc(ImgComponent_t *, 0);

      imgComp->func = NIL(mdd_t);
      ImgComponentFree(imgComp);

      imgComp = ImgComponentAlloc(info);
      imgComp->func = newImage;
      ImgSupportClear(info, imgComp->support);
      ImgComponentGetSupport(imgComp);
      for (i = 0; i < array_n(tmpVector); i++) {
        comp = array_fetch(ImgComponent_t *, tmpVector, i);
        id = (int)bdd_top_var_id(comp->var);
        if (imgComp->support[id] || comp->intermediate)
          array_insert_last(ImgComponent_t *, *newVector, comp);
        else {
          if (abstract) {
            nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
            tmp = abstract;
            abstract = mdd_and(tmp, nsVar, 1, 1);
            mdd_free(tmp);
            mdd_free(nsVar);
          }
          ImgComponentFree(comp);
        }
      }
      array_free(tmpVector);
    } else
      *newVector = tmpVector;
  } else {
    newImage = image;
    *newVector = vector;
    cofactor = NIL(mdd_t);
    abstract = NIL(mdd_t);
  }

  yVarsCube = mdd_one(info->manager);
  for (i = 0; i < info->nVars; i++) {
    if (imgComp->support[i]) {
      imgComp->support[i] = 0;
      if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
        continue;
      if (info->intermediateVarsTable &&
          st_lookup(info->intermediateVarsTable, (char *)(long)i,
                    NIL(char *))) {
        continue;
      }
      var = bdd_var_with_index(info->manager, i);
      nsVar = ImgSubstitute(var, info->functionData, Img_D2R_c);
      mdd_free(var);
      id = (int)bdd_top_var_id(nsVar);
      imgComp->support[id] = 1;
      tmp = yVarsCube;
      yVarsCube = mdd_and(tmp, nsVar, 1, 1);
      mdd_free(tmp);
      mdd_free(nsVar);
    }
  }

  if (vector) {
    for (i = 0; i < array_n(*newVector); i++) {
      comp = array_fetch(ImgComponent_t *, *newVector, i);
      nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
      id = (int)bdd_top_var_id(nsVar);
      imgComp->support[id] = 2;
      mdd_free(nsVar);
    }
  }

  for (i = 0; i < array_n(relationArray); i++) {
    relation = array_fetch(mdd_t *, relationArray, i);
    supportIds = mdd_get_bdd_support_ids(info->manager, relation);
    for (j = 0; j < array_n(supportIds); j++) {
      id = array_fetch(int, supportIds, j);
      imgComp->support[id] = 2;
    }
    array_free(supportIds);
  }

  for (i = 0; i < info->nVars; i++) {
    if (imgComp->support[i] == 1) {
      nsVar = bdd_var_with_index(info->manager, i);
      var = ImgSubstitute(nsVar, info->functionData, Img_R2D_c);
      mdd_free(nsVar);
      tmp = newImage;
      newImage = bdd_smooth_with_cube(tmp, var);
      if (tmp != image)
        mdd_free(tmp);
      mdd_free(var);
    }
  }

  imgComp->func = NIL(mdd_t);
  ImgComponentFree(imgComp);

  if (bdd_get_package_name() == CUDD)
    rangeCube = info->functionData->rangeCube;
  else {
    rangeCube = mdd_one(info->manager);
    for (i = 0; i < array_n(info->functionData->rangeBddVars); i++) {
      var = array_fetch(mdd_t *, info->functionData->rangeBddVars, i);
      tmp = rangeCube;
      rangeCube = mdd_and(tmp, var, 1, 1);
      mdd_free(tmp);
    }
  }

  cofactor = NIL(mdd_t);
  if (abstract) {
    tmp2 = bdd_smooth_with_cube(rangeCube, yVarsCube);
    tmp = abstract;
    abstract = mdd_and(tmp, tmp2, 1, 1);
    mdd_free(tmp);
    mdd_free(tmp2);
  } else
    abstract = bdd_smooth_with_cube(rangeCube, yVarsCube);
  mdd_free(yVarsCube);
  if (rangeCube != info->functionData->rangeCube)
    mdd_free(rangeCube);

  *newRelationArray = relationArray;
  if (cofactor) {
    if (!bdd_is_tautology(cofactor, 1)) {
      tmpRelationArray = *newRelationArray;
      *newRelationArray = ImgGetCofactoredRelationArray(tmpRelationArray,
                                                        cofactor);
      if (tmpRelationArray != relationArray)
        mdd_array_free(tmpRelationArray);
    }
    mdd_free(cofactor);
  }
  if (bdd_is_tautology(abstract, 1))
    mdd_free(abstract);
  else {
    tmpRelationArray = *newRelationArray;
    *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
                                                      tmpRelationArray,
                                                      abstract);
    mdd_free(abstract);
    if (tmpRelationArray != relationArray)
      mdd_array_free(tmpRelationArray);
  }
  return(newImage);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bdd_t * PreImageMakeVectorCanonical ( ImgTfmInfo_t *  info,
array_t *  vector,
bdd_t *  image,
array_t *  relationArray,
array_t **  newVector,
array_t **  newRelationArray,
mdd_t **  cofactorCube,
mdd_t **  abstractCube 
) [static]

Function********************************************************************

Synopsis [Makes a vector canonical for preimage.]

Description [Makes a vector canonical for preimage. Delete all the components which doesn't appear as a support in the image. If a component is constant, simplify the image with the constant value and delete the corresponding component from delta Side effect on delta. Return new image.]

SideEffects []

Definition at line 1612 of file imgTfmBwd.c.

{
  array_t               *tmpVector, *cofactoredVector;
  bdd_t                 *simple, *tmp, *newImage;
  ImgComponent_t        *comp, *comp1, *imgComp;
  int                   i, id, n, pos;
  st_table              *equivTable;
  int                   *ptr, *regularPtr;
  mdd_t                 *var, *cofactor, *abstract, *nsVar;
  array_t               *tmpRelationArray;
  int                   changed = 0;

  newImage = mdd_dup(image);

  imgComp = ImgComponentAlloc(info);
  imgComp->func = image;
  ImgComponentGetSupport(imgComp);

  if (relationArray) {
    cofactor = mdd_one(info->manager);
    abstract = mdd_one(info->manager);
  } else {
    cofactor = NIL(mdd_t);
    abstract = NIL(mdd_t);
  }

  if (info->nIntermediateVars) {
    mdd_t       *tmpCofactor, *tmpAbstract;
    mdd_t       *constIntermediate;

    if (ImgExistConstIntermediateVar(vector)) {
      constIntermediate = mdd_one(info->manager);
      for (i = 0; i < array_n(vector); i++) {
        comp = array_fetch(ImgComponent_t *, vector, i);
        if (comp->intermediate) {
          if (mdd_is_tautology(comp->func, 1)) {
            tmp = constIntermediate;
            constIntermediate = mdd_and(tmp, comp->var, 1, 1);
            mdd_free(tmp);
          } else if (mdd_is_tautology(comp->func, 0)) {
            tmp = constIntermediate;
            constIntermediate = mdd_and(tmp, comp->var, 1, 0);
            mdd_free(tmp);
          }
        }
      }
      if (relationArray) {
        cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
                                                  constIntermediate,
                                                  &tmpCofactor, &tmpAbstract,
                                                  NIL(mdd_t *), &newImage);

        if (!bdd_is_tautology(tmpCofactor, 1)) {
          tmp = cofactor;
          cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpCofactor);
        if (!bdd_is_tautology(tmpAbstract, 1)) {
          tmp = abstract;
          abstract = mdd_and(tmp, tmpAbstract, 1, 1);
          mdd_free(tmp);
        }
        mdd_free(tmpAbstract);
      } else {
        cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
                                                  constIntermediate,
                                                  NIL(mdd_t *), NIL(mdd_t *),
                                                  NIL(mdd_t *), &newImage);
      }
      mdd_free(constIntermediate);
    } else
      cofactoredVector = vector;
  } else
    cofactoredVector = vector;

  /* Simplify image -- canonicalize the image first */
  n = 0;
  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
  tmpVector = array_alloc(ImgComponent_t *, 0);
  for (i = 0; i < array_n(cofactoredVector); i++) {
    comp = array_fetch(ImgComponent_t *, cofactoredVector, i);
    if (comp->intermediate) {
      comp1 = ImgComponentCopy(info, comp);
      array_insert_last(ImgComponent_t *, tmpVector, comp1);
      n++;
      continue;
    }
    id = (int)bdd_top_var_id(comp->var);
    if (!imgComp->support[id]) {
      if (abstract) {
        nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
        tmp = abstract;
        abstract = mdd_and(tmp, nsVar, 1, 1);
        mdd_free(tmp);
        mdd_free(nsVar);
      }
      continue;
    }
    if (mdd_is_tautology(comp->func, 1)) {
      changed = 1;
      simple = bdd_cofactor(newImage, comp->var);
      mdd_free(newImage);
      newImage = simple;
      if (abstract) {
        nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
        tmp = abstract;
        abstract = mdd_and(tmp, nsVar, 1, 1);
        mdd_free(tmp);
        mdd_free(nsVar);
      }
    } else if (mdd_is_tautology(comp->func, 0)) {
      changed = 1;
      tmp = mdd_not(comp->var);
      simple = bdd_cofactor(newImage, tmp);
      mdd_free(tmp);
      mdd_free(newImage);
      newImage = simple;
      if (abstract) {
        nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
        tmp = abstract;
        abstract = mdd_and(tmp, nsVar, 1, 1);
        mdd_free(tmp);
        mdd_free(nsVar);
      }
    } else {
      ptr = (int *)bdd_pointer(comp->func);
      regularPtr = (int *)((unsigned long)ptr & ~01);
      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
        changed = 1;
        comp1 = array_fetch(ImgComponent_t *, tmpVector, pos);
        if (mdd_equal(comp->func, comp1->func)) {
          tmp = newImage;
          newImage = bdd_compose(tmp, comp->var, comp1->var);
          mdd_free(tmp);
        } else {
          tmp = newImage;
          var = mdd_not(comp1->var);
          newImage = bdd_compose(tmp, comp->var, var);
          mdd_free(tmp);
          mdd_free(var);
        }
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
      } else {
        comp1 = ImgComponentCopy(info, comp);
        array_insert_last(ImgComponent_t *, tmpVector, comp1);
        st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
        n++;
      }
    }
  }
  st_free_table(equivTable);
  if (cofactoredVector && cofactoredVector != vector)
    ImgVectorFree(cofactoredVector);

  if (changed) {
    /* Now Simplify delta by deleting the non-affecting components */
    *newVector = array_alloc(ImgComponent_t *, 0);

    imgComp->func = NIL(mdd_t);
    ImgComponentFree(imgComp);

    imgComp = ImgComponentAlloc(info);
    imgComp->func = newImage;
    ImgSupportClear(info, imgComp->support);
    ImgComponentGetSupport(imgComp);
    for (i = 0; i < array_n(tmpVector); i++) {
      comp = array_fetch(ImgComponent_t *, tmpVector, i);
      id = (int)bdd_top_var_id(comp->var);
      if (imgComp->support[id] || comp->intermediate)
        array_insert_last(ImgComponent_t *, *newVector, comp);
      else {
        if (abstract) {
          nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
          tmp = abstract;
          abstract = mdd_and(tmp, nsVar, 1, 1);
          mdd_free(tmp);
          mdd_free(nsVar);
        }
        ImgComponentFree(comp);
      }
    }
    array_free(tmpVector);
  } else
    *newVector = tmpVector;

  imgComp->func = NIL(mdd_t);
  ImgComponentFree(imgComp);

  if (newRelationArray)
    *newRelationArray = relationArray;
  if (cofactor) {
    if (cofactorCube)
      *cofactorCube = cofactor;
    else {
      if (!bdd_is_tautology(cofactor, 1)) {
        tmpRelationArray = *newRelationArray;
        *newRelationArray = ImgGetCofactoredRelationArray(tmpRelationArray,
                                                          cofactor);
        if (tmpRelationArray != relationArray)
          mdd_array_free(tmpRelationArray);
      }
      mdd_free(cofactor);
    }
  }
  if (abstract) {
    if (abstractCube)
      *abstractCube = abstract;
    else {
      if (bdd_is_tautology(abstract, 1))
        mdd_free(abstract);
      else {
        tmpRelationArray = *newRelationArray;
        *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
                                                          tmpRelationArray,
                                                          abstract);
        mdd_free(abstract);
        if (tmpRelationArray != relationArray)
          mdd_array_free(tmpRelationArray);
      }
    }
  }
  assert(CheckPreImageVector(info, *newVector, newImage));
  return(newImage);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char rcsid [] UNUSED = "$Id: imgTfmBwd.c,v 1.29 2002/08/18 04:47:07 fabio Exp $" [static]

CFile***********************************************************************

FileName [imgTfmBwd.c]

PackageName [img]

Synopsis [Routines for preimage computation using transition function method.]

Description []

SeeAlso []

Author [In-Ho Moon]

Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado. All rights reserved.

Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software.

IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]

Definition at line 38 of file imgTfmBwd.c.