#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | CUDD_SWAP_MOVE 0 |
#define | CUDD_LINEAR_TRANSFORM_MOVE 1 |
#define | CUDD_INVERSE_TRANSFORM_MOVE 2 |
#define | BPL 32 |
#define | LOGBPL 5 |
Functions | |
static int ddLinearUniqueCompare | ARGS ((int *ptrX, int *ptrY)) |
static int ddLinearAndSiftingAux | ARGS ((DdManager *table, int x, int xLow, int xHigh)) |
static Move *ddLinearAndSiftingUp | ARGS ((DdManager *table, int y, int xLow, Move *prevMoves)) |
static Move *ddLinearAndSiftingDown | ARGS ((DdManager *table, int x, int xHigh, Move *prevMoves)) |
static int ddLinearAndSiftingBackward | ARGS ((DdManager *table, int size, Move *moves)) |
static Move *ddUndoMoves | ARGS ((DdManager *table, Move *moves)) |
static int cuddLinearInPlace | ARGS ((DdManager *table, int x, int y)) |
static void ddUpdateInteractionMatrix | ARGS ((DdManager *table, int xindex, int yindex)) |
static int cuddInitLinear | ARGS ((DdManager *table)) |
int | Cudd_PrintLinear (DdManager *table) |
int | Cudd_ReadLinear (DdManager *table, int x, int y) |
int | cuddLinearAndSifting (DdManager *table, int lower, int upper) |
static int | ddLinearUniqueCompare (int *ptrX, int *ptrY) |
static int | ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh) |
static Move * | ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves) |
static Move * | ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves) |
static int | ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves) |
static Move * | ddUndoMoves (DdManager *table, Move *moves) |
static int | cuddLinearInPlace (DdManager *table, int x, int y) |
static void | ddUpdateInteractionMatrix (DdManager *table, int xindex, int yindex) |
static int | cuddInitLinear (DdManager *table) |
static int | cuddResizeLinear (DdManager *table) |
static void | cuddXorLinear (DdManager *table, int x, int y) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $" |
static int * | entry |
#define BPL 32 |
Definition at line 51 of file cuddLinear.c.
#define CUDD_INVERSE_TRANSFORM_MOVE 2 |
Definition at line 46 of file cuddLinear.c.
#define CUDD_LINEAR_TRANSFORM_MOVE 1 |
Definition at line 45 of file cuddLinear.c.
#define CUDD_SWAP_MOVE 0 |
CFile***********************************************************************
FileName [cuddLinear.c]
PackageName [cudd]
Synopsis [Functions for DD reduction by linear transformations.]
Description [ Internal procedures included in this module:
Static procedures included in this module:
]
Author [Fabio Somenzi]
Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]
Definition at line 44 of file cuddLinear.c.
#define LOGBPL 5 |
Definition at line 52 of file cuddLinear.c.
static int cuddInitLinear ARGS | ( | (DdManager *table) | ) | [static] |
static void ddUpdateInteractionMatrix ARGS | ( | (DdManager *table, int xindex, int yindex) | ) | [static] |
static int cuddLinearInPlace ARGS | ( | (DdManager *table, int x, int y) | ) | [static] |
static Move* ddLinearAndSiftingDown ARGS | ( | (DdManager *table, int x, int xHigh, Move *prevMoves) | ) | [static] |
static Move* ddLinearAndSiftingUp ARGS | ( | (DdManager *table, int y, int xLow, Move *prevMoves) | ) | [static] |
static int ddLinearAndSiftingAux ARGS | ( | (DdManager *table, int x, int xLow, int xHigh) | ) | [static] |
static int ddLinearUniqueCompare ARGS | ( | (int *ptrX, int *ptrY) | ) | [static] |
AutomaticStart
int Cudd_PrintLinear | ( | DdManager * | table | ) |
AutomaticEnd Function********************************************************************
Synopsis [Prints the linear transform matrix.]
Description [Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.]
SideEffects [none]
SeeAlso []
Definition at line 126 of file cuddLinear.c.
00128 { 00129 int i,j,k; 00130 int retval; 00131 int nvars = table->linearSize; 00132 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00133 long word; 00134 00135 for (i = 0; i < nvars; i++) { 00136 for (j = 0; j < wordsPerRow; j++) { 00137 word = table->linear[i*wordsPerRow + j]; 00138 for (k = 0; k < BPL; k++) { 00139 retval = fprintf(table->out,"%ld",word & 1); 00140 if (retval == 0) return(0); 00141 word >>= 1; 00142 } 00143 } 00144 retval = fprintf(table->out,"\n"); 00145 if (retval == 0) return(0); 00146 } 00147 return(1); 00148 00149 } /* end of Cudd_PrintLinear */
int Cudd_ReadLinear | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) |
Function********************************************************************
Synopsis [Reads an entry of the linear transform matrix.]
Description [Reads an entry of the linear transform matrix.]
SideEffects [none]
SeeAlso []
Definition at line 164 of file cuddLinear.c.
00168 { 00169 int nvars = table->size; 00170 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 00171 long word; 00172 int bit; 00173 int result; 00174 00175 assert(table->size == table->linearSize); 00176 00177 word = wordsPerRow * x + (y >> LOGBPL); 00178 bit = y & (BPL-1); 00179 result = (int) ((table->linear[word] >> bit) & 1); 00180 return(result); 00181 00182 } /* end of Cudd_ReadLinear */
static int cuddInitLinear | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Initializes the linear transform matrix.]
Description []
SideEffects [none]
SeeAlso []
Definition at line 1209 of file cuddLinear.c.
01211 { 01212 int words; 01213 int wordsPerRow; 01214 int nvars; 01215 int word; 01216 int bit; 01217 int i; 01218 long *linear; 01219 01220 nvars = table->size; 01221 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 01222 words = wordsPerRow * nvars; 01223 table->linear = linear = ALLOC(long,words); 01224 if (linear == NULL) { 01225 table->errorCode = CUDD_MEMORY_OUT; 01226 return(0); 01227 } 01228 table->memused += words * sizeof(long); 01229 table->linearSize = nvars; 01230 for (i = 0; i < words; i++) linear[i] = 0; 01231 for (i = 0; i < nvars; i++) { 01232 word = wordsPerRow * i + (i >> LOGBPL); 01233 bit = i & (BPL-1); 01234 linear[word] = 1 << bit; 01235 } 01236 return(1); 01237 01238 } /* end of cuddInitLinear */
int cuddLinearAndSifting | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
Function********************************************************************
Synopsis [BDD reduction based on combination of sifting and linear transformations.]
Description [BDD reduction based on combination of sifting and linear transformations. Assumes that no dead nodes are present.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 213 of file cuddLinear.c.
00217 { 00218 int i; 00219 int *var; 00220 int size; 00221 int x; 00222 int result; 00223 #ifdef DD_STATS 00224 int previousSize; 00225 #endif 00226 00227 #ifdef DD_STATS 00228 ddTotalNumberLinearTr = 0; 00229 #endif 00230 00231 size = table->size; 00232 00233 var = NULL; 00234 entry = NULL; 00235 if (table->linear == NULL) { 00236 result = cuddInitLinear(table); 00237 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00238 #if 0 00239 (void) fprintf(table->out,"\n"); 00240 result = Cudd_PrintLinear(table); 00241 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00242 #endif 00243 } else if (table->size != table->linearSize) { 00244 result = cuddResizeLinear(table); 00245 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00246 #if 0 00247 (void) fprintf(table->out,"\n"); 00248 result = Cudd_PrintLinear(table); 00249 if (result == 0) goto cuddLinearAndSiftingOutOfMem; 00250 #endif 00251 } 00252 00253 /* Find order in which to sift variables. */ 00254 entry = ALLOC(int,size); 00255 if (entry == NULL) { 00256 table->errorCode = CUDD_MEMORY_OUT; 00257 goto cuddLinearAndSiftingOutOfMem; 00258 } 00259 var = ALLOC(int,size); 00260 if (var == NULL) { 00261 table->errorCode = CUDD_MEMORY_OUT; 00262 goto cuddLinearAndSiftingOutOfMem; 00263 } 00264 00265 for (i = 0; i < size; i++) { 00266 x = table->perm[i]; 00267 entry[i] = table->subtables[x].keys; 00268 var[i] = i; 00269 } 00270 00271 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare); 00272 00273 /* Now sift. */ 00274 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { 00275 x = table->perm[var[i]]; 00276 if (x < lower || x > upper) continue; 00277 #ifdef DD_STATS 00278 previousSize = table->keys - table->isolated; 00279 #endif 00280 result = ddLinearAndSiftingAux(table,x,lower,upper); 00281 if (!result) goto cuddLinearAndSiftingOutOfMem; 00282 #ifdef DD_STATS 00283 if (table->keys < (unsigned) previousSize + table->isolated) { 00284 (void) fprintf(table->out,"-"); 00285 } else if (table->keys > (unsigned) previousSize + table->isolated) { 00286 (void) fprintf(table->out,"+"); /* should never happen */ 00287 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); 00288 } else { 00289 (void) fprintf(table->out,"="); 00290 } 00291 fflush(table->out); 00292 #endif 00293 #ifdef DD_DEBUG 00294 (void) Cudd_DebugCheck(table); 00295 #endif 00296 } 00297 00298 FREE(var); 00299 FREE(entry); 00300 00301 #ifdef DD_STATS 00302 (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", 00303 ddTotalNumberLinearTr); 00304 #endif 00305 00306 return(1); 00307 00308 cuddLinearAndSiftingOutOfMem: 00309 00310 if (entry != NULL) FREE(entry); 00311 if (var != NULL) FREE(var); 00312 00313 return(0); 00314 00315 } /* end of cuddLinearAndSifting */
static int cuddLinearInPlace | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [Linearly combines two adjacent variables.]
Description [Linearly combines two adjacent variables. Specifically, replaces the top variable with the exclusive nor of the two variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]
SideEffects [The two subtables corrresponding to variables x and y are modified. The global counters of the unique table are also affected.]
SeeAlso [cuddSwapInPlace]
Definition at line 823 of file cuddLinear.c.
00827 { 00828 DdNodePtr *xlist, *ylist; 00829 int xindex, yindex; 00830 int xslots, yslots; 00831 int xshift, yshift; 00832 int oldxkeys, oldykeys; 00833 int newxkeys, newykeys; 00834 int comple, newcomplement; 00835 int i; 00836 int posn; 00837 int isolated; 00838 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; 00839 DdNode *g,*next,*last; 00840 DdNodePtr *previousP; 00841 DdNode *tmp; 00842 DdNode *sentinel = &(table->sentinel); 00843 #if DD_DEBUG 00844 int count, idcheck; 00845 #endif 00846 00847 #ifdef DD_DEBUG 00848 assert(x < y); 00849 assert(cuddNextHigh(table,x) == y); 00850 assert(table->subtables[x].keys != 0); 00851 assert(table->subtables[y].keys != 0); 00852 assert(table->subtables[x].dead == 0); 00853 assert(table->subtables[y].dead == 0); 00854 #endif 00855 00856 xindex = table->invperm[x]; 00857 yindex = table->invperm[y]; 00858 00859 if (cuddTestInteract(table,xindex,yindex)) { 00860 #ifdef DD_STATS 00861 ddTotalNumberLinearTr++; 00862 #endif 00863 /* Get parameters of x subtable. */ 00864 xlist = table->subtables[x].nodelist; 00865 oldxkeys = table->subtables[x].keys; 00866 xslots = table->subtables[x].slots; 00867 xshift = table->subtables[x].shift; 00868 00869 /* Get parameters of y subtable. */ 00870 ylist = table->subtables[y].nodelist; 00871 oldykeys = table->subtables[y].keys; 00872 yslots = table->subtables[y].slots; 00873 yshift = table->subtables[y].shift; 00874 00875 newxkeys = 0; 00876 newykeys = oldykeys; 00877 00878 /* Check whether the two projection functions involved in this 00879 ** swap are isolated. At the end, we'll be able to tell how many 00880 ** isolated projection functions are there by checking only these 00881 ** two functions again. This is done to eliminate the isolated 00882 ** projection functions from the node count. 00883 */ 00884 isolated = - ((table->vars[xindex]->ref == 1) + 00885 (table->vars[yindex]->ref == 1)); 00886 00887 /* The nodes in the x layer are put in a chain. 00888 ** The chain is handled as a FIFO; g points to the beginning and 00889 ** last points to the end. 00890 */ 00891 g = NULL; 00892 for (i = 0; i < xslots; i++) { 00893 f = xlist[i]; 00894 if (f == sentinel) continue; 00895 xlist[i] = sentinel; 00896 if (g == NULL) { 00897 g = f; 00898 } else { 00899 last->next = f; 00900 } 00901 while ((next = f->next) != sentinel) { 00902 f = next; 00903 } /* while there are elements in the collision chain */ 00904 last = f; 00905 } /* for each slot of the x subtable */ 00906 last->next = NULL; 00907 00908 #ifdef DD_COUNT 00909 table->swapSteps += oldxkeys; 00910 #endif 00911 /* Take care of the x nodes that must be re-expressed. 00912 ** They form a linked list pointed by g. 00913 */ 00914 f = g; 00915 while (f != NULL) { 00916 next = f->next; 00917 /* Find f1, f0, f11, f10, f01, f00. */ 00918 f1 = cuddT(f); 00919 #ifdef DD_DEBUG 00920 assert(!(Cudd_IsComplement(f1))); 00921 #endif 00922 if ((int) f1->index == yindex) { 00923 f11 = cuddT(f1); f10 = cuddE(f1); 00924 } else { 00925 f11 = f10 = f1; 00926 } 00927 #ifdef DD_DEBUG 00928 assert(!(Cudd_IsComplement(f11))); 00929 #endif 00930 f0 = cuddE(f); 00931 comple = Cudd_IsComplement(f0); 00932 f0 = Cudd_Regular(f0); 00933 if ((int) f0->index == yindex) { 00934 f01 = cuddT(f0); f00 = cuddE(f0); 00935 } else { 00936 f01 = f00 = f0; 00937 } 00938 if (comple) { 00939 f01 = Cudd_Not(f01); 00940 f00 = Cudd_Not(f00); 00941 } 00942 /* Decrease ref count of f1. */ 00943 cuddSatDec(f1->ref); 00944 /* Create the new T child. */ 00945 if (f11 == f00) { 00946 newf1 = f11; 00947 cuddSatInc(newf1->ref); 00948 } else { 00949 /* Check ylist for triple (yindex,f11,f00). */ 00950 posn = ddHash(f11, f00, yshift); 00951 /* For each element newf1 in collision list ylist[posn]. */ 00952 previousP = &(ylist[posn]); 00953 newf1 = *previousP; 00954 while (f11 < cuddT(newf1)) { 00955 previousP = &(newf1->next); 00956 newf1 = *previousP; 00957 } 00958 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { 00959 previousP = &(newf1->next); 00960 newf1 = *previousP; 00961 } 00962 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { 00963 cuddSatInc(newf1->ref); 00964 } else { /* no match */ 00965 newf1 = cuddDynamicAllocNode(table); 00966 if (newf1 == NULL) 00967 goto cuddLinearOutOfMem; 00968 newf1->index = yindex; newf1->ref = 1; 00969 cuddT(newf1) = f11; 00970 cuddE(newf1) = f00; 00971 /* Insert newf1 in the collision list ylist[posn]; 00972 ** increase the ref counts of f11 and f00. 00973 */ 00974 newykeys++; 00975 newf1->next = *previousP; 00976 *previousP = newf1; 00977 cuddSatInc(f11->ref); 00978 tmp = Cudd_Regular(f00); 00979 cuddSatInc(tmp->ref); 00980 } 00981 } 00982 cuddT(f) = newf1; 00983 #ifdef DD_DEBUG 00984 assert(!(Cudd_IsComplement(newf1))); 00985 #endif 00986 00987 /* Do the same for f0, keeping complement dots into account. */ 00988 /* decrease ref count of f0 */ 00989 tmp = Cudd_Regular(f0); 00990 cuddSatDec(tmp->ref); 00991 /* create the new E child */ 00992 if (f01 == f10) { 00993 newf0 = f01; 00994 tmp = Cudd_Regular(newf0); 00995 cuddSatInc(tmp->ref); 00996 } else { 00997 /* make sure f01 is regular */ 00998 newcomplement = Cudd_IsComplement(f01); 00999 if (newcomplement) { 01000 f01 = Cudd_Not(f01); 01001 f10 = Cudd_Not(f10); 01002 } 01003 /* Check ylist for triple (yindex,f01,f10). */ 01004 posn = ddHash(f01, f10, yshift); 01005 /* For each element newf0 in collision list ylist[posn]. */ 01006 previousP = &(ylist[posn]); 01007 newf0 = *previousP; 01008 while (f01 < cuddT(newf0)) { 01009 previousP = &(newf0->next); 01010 newf0 = *previousP; 01011 } 01012 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { 01013 previousP = &(newf0->next); 01014 newf0 = *previousP; 01015 } 01016 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { 01017 cuddSatInc(newf0->ref); 01018 } else { /* no match */ 01019 newf0 = cuddDynamicAllocNode(table); 01020 if (newf0 == NULL) 01021 goto cuddLinearOutOfMem; 01022 newf0->index = yindex; newf0->ref = 1; 01023 cuddT(newf0) = f01; 01024 cuddE(newf0) = f10; 01025 /* Insert newf0 in the collision list ylist[posn]; 01026 ** increase the ref counts of f01 and f10. 01027 */ 01028 newykeys++; 01029 newf0->next = *previousP; 01030 *previousP = newf0; 01031 cuddSatInc(f01->ref); 01032 tmp = Cudd_Regular(f10); 01033 cuddSatInc(tmp->ref); 01034 } 01035 if (newcomplement) { 01036 newf0 = Cudd_Not(newf0); 01037 } 01038 } 01039 cuddE(f) = newf0; 01040 01041 /* Re-insert the modified f in xlist. 01042 ** The modified f does not already exists in xlist. 01043 ** (Because of the uniqueness of the cofactors.) 01044 */ 01045 posn = ddHash(newf1, newf0, xshift); 01046 newxkeys++; 01047 previousP = &(xlist[posn]); 01048 tmp = *previousP; 01049 while (newf1 < cuddT(tmp)) { 01050 previousP = &(tmp->next); 01051 tmp = *previousP; 01052 } 01053 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { 01054 previousP = &(tmp->next); 01055 tmp = *previousP; 01056 } 01057 f->next = *previousP; 01058 *previousP = f; 01059 f = next; 01060 } /* while f != NULL */ 01061 01062 /* GC the y layer. */ 01063 01064 /* For each node f in ylist. */ 01065 for (i = 0; i < yslots; i++) { 01066 previousP = &(ylist[i]); 01067 f = *previousP; 01068 while (f != sentinel) { 01069 next = f->next; 01070 if (f->ref == 0) { 01071 tmp = cuddT(f); 01072 cuddSatDec(tmp->ref); 01073 tmp = Cudd_Regular(cuddE(f)); 01074 cuddSatDec(tmp->ref); 01075 cuddDeallocNode(table,f); 01076 newykeys--; 01077 } else { 01078 *previousP = f; 01079 previousP = &(f->next); 01080 } 01081 f = next; 01082 } /* while f */ 01083 *previousP = sentinel; 01084 } /* for every collision list */ 01085 01086 #if DD_DEBUG 01087 #if 0 01088 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); 01089 #endif 01090 count = 0; 01091 idcheck = 0; 01092 for (i = 0; i < yslots; i++) { 01093 f = ylist[i]; 01094 while (f != sentinel) { 01095 count++; 01096 if (f->index != (DdHalfWord) yindex) 01097 idcheck++; 01098 f = f->next; 01099 } 01100 } 01101 if (count != newykeys) { 01102 fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); 01103 } 01104 if (idcheck != 0) 01105 fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); 01106 count = 0; 01107 idcheck = 0; 01108 for (i = 0; i < xslots; i++) { 01109 f = xlist[i]; 01110 while (f != sentinel) { 01111 count++; 01112 if (f->index != (DdHalfWord) xindex) 01113 idcheck++; 01114 f = f->next; 01115 } 01116 } 01117 if (count != newxkeys || newxkeys != oldxkeys) { 01118 fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); 01119 } 01120 if (idcheck != 0) 01121 fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); 01122 #endif 01123 01124 isolated += (table->vars[xindex]->ref == 1) + 01125 (table->vars[yindex]->ref == 1); 01126 table->isolated += isolated; 01127 01128 /* Set the appropriate fields in table. */ 01129 table->subtables[y].keys = newykeys; 01130 01131 /* Here we should update the linear combination table 01132 ** to record that x <- x EXNOR y. This is done by complementing 01133 ** the (x,y) entry of the table. 01134 */ 01135 01136 table->keys += newykeys - oldykeys; 01137 01138 cuddXorLinear(table,xindex,yindex); 01139 } 01140 01141 #ifdef DD_DEBUG 01142 if (zero) { 01143 (void) Cudd_DebugCheck(table); 01144 } 01145 #endif 01146 01147 return(table->keys - table->isolated); 01148 01149 cuddLinearOutOfMem: 01150 (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); 01151 01152 return (0); 01153 01154 } /* end of cuddLinearInPlace */
static int cuddResizeLinear | ( | DdManager * | table | ) | [static] |
Function********************************************************************
Synopsis [Resizes the linear transform matrix.]
Description []
SideEffects [none]
SeeAlso []
Definition at line 1253 of file cuddLinear.c.
01255 { 01256 int words,oldWords; 01257 int wordsPerRow,oldWordsPerRow; 01258 int nvars,oldNvars; 01259 int word,oldWord; 01260 int bit; 01261 int i,j; 01262 long *linear,*oldLinear; 01263 01264 oldNvars = table->linearSize; 01265 oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; 01266 oldWords = oldWordsPerRow * oldNvars; 01267 oldLinear = table->linear; 01268 01269 nvars = table->size; 01270 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 01271 words = wordsPerRow * nvars; 01272 table->linear = linear = ALLOC(long,words); 01273 if (linear == NULL) { 01274 table->errorCode = CUDD_MEMORY_OUT; 01275 return(0); 01276 } 01277 table->memused += (words - oldWords) * sizeof(long); 01278 for (i = 0; i < words; i++) linear[i] = 0; 01279 01280 /* Copy old matrix. */ 01281 for (i = 0; i < oldNvars; i++) { 01282 for (j = 0; j < oldWordsPerRow; j++) { 01283 oldWord = oldWordsPerRow * i + j; 01284 word = wordsPerRow * i + j; 01285 linear[word] = oldLinear[oldWord]; 01286 } 01287 } 01288 FREE(oldLinear); 01289 01290 /* Add elements to the diagonal. */ 01291 for (i = oldNvars; i < nvars; i++) { 01292 word = wordsPerRow * i + (i >> LOGBPL); 01293 bit = i & (BPL-1); 01294 linear[word] = 1 << bit; 01295 } 01296 table->linearSize = nvars; 01297 01298 return(1); 01299 01300 } /* end of cuddResizeLinear */
static void cuddXorLinear | ( | DdManager * | table, | |
int | x, | |||
int | y | |||
) | [static] |
Function********************************************************************
Synopsis [XORs two rows of the linear transform matrix.]
Description [XORs two rows of the linear transform matrix and replaces the first row with the result.]
SideEffects [none]
SeeAlso []
Definition at line 1316 of file cuddLinear.c.
01320 { 01321 int i; 01322 int nvars = table->size; 01323 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; 01324 int xstart = wordsPerRow * x; 01325 int ystart = wordsPerRow * y; 01326 long *linear = table->linear; 01327 01328 for (i = 0; i < wordsPerRow; i++) { 01329 linear[xstart+i] ^= linear[ystart+i]; 01330 } 01331 01332 } /* end of cuddXorLinear */
static int ddLinearAndSiftingAux | ( | DdManager * | table, | |
int | x, | |||
int | xLow, | |||
int | xHigh | |||
) | [static] |
Function********************************************************************
Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]
Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. At each step a linear transformation is tried, and, if it decreases the size of the DD, it is accepted. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
Definition at line 364 of file cuddLinear.c.
00369 { 00370 00371 Move *move; 00372 Move *moveUp; /* list of up moves */ 00373 Move *moveDown; /* list of down moves */ 00374 int initialSize; 00375 int result; 00376 00377 initialSize = table->keys - table->isolated; 00378 00379 moveDown = NULL; 00380 moveUp = NULL; 00381 00382 if (x == xLow) { 00383 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); 00384 /* At this point x --> xHigh unless bounding occurred. */ 00385 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00386 /* Move backward and stop at best position. */ 00387 result = ddLinearAndSiftingBackward(table,initialSize,moveDown); 00388 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00389 00390 } else if (x == xHigh) { 00391 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); 00392 /* At this point x --> xLow unless bounding occurred. */ 00393 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00394 /* Move backward and stop at best position. */ 00395 result = ddLinearAndSiftingBackward(table,initialSize,moveUp); 00396 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00397 00398 } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ 00399 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); 00400 /* At this point x --> xHigh unless bounding occurred. */ 00401 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00402 moveUp = ddUndoMoves(table,moveDown); 00403 #ifdef DD_DEBUG 00404 assert(moveUp == NULL || moveUp->x == x); 00405 #endif 00406 moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); 00407 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00408 /* Move backward and stop at best position. */ 00409 result = ddLinearAndSiftingBackward(table,initialSize,moveUp); 00410 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00411 00412 } else { /* must go up first: shorter */ 00413 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); 00414 /* At this point x --> xLow unless bounding occurred. */ 00415 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00416 moveDown = ddUndoMoves(table,moveUp); 00417 #ifdef DD_DEBUG 00418 assert(moveDown == NULL || moveDown->y == x); 00419 #endif 00420 moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); 00421 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; 00422 /* Move backward and stop at best position. */ 00423 result = ddLinearAndSiftingBackward(table,initialSize,moveDown); 00424 if (!result) goto ddLinearAndSiftingAuxOutOfMem; 00425 } 00426 00427 while (moveDown != NULL) { 00428 move = moveDown->next; 00429 cuddDeallocNode(table, (DdNode *) moveDown); 00430 moveDown = move; 00431 } 00432 while (moveUp != NULL) { 00433 move = moveUp->next; 00434 cuddDeallocNode(table, (DdNode *) moveUp); 00435 moveUp = move; 00436 } 00437 00438 return(1); 00439 00440 ddLinearAndSiftingAuxOutOfMem: 00441 while (moveDown != NULL) { 00442 move = moveDown->next; 00443 cuddDeallocNode(table, (DdNode *) moveDown); 00444 moveDown = move; 00445 } 00446 while (moveUp != NULL) { 00447 move = moveUp->next; 00448 cuddDeallocNode(table, (DdNode *) moveUp); 00449 moveUp = move; 00450 } 00451 00452 return(0); 00453 00454 } /* end of ddLinearAndSiftingAux */
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the order giving the minimum size.]
Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 706 of file cuddLinear.c.
00710 { 00711 Move *move; 00712 int res; 00713 00714 for (move = moves; move != NULL; move = move->next) { 00715 if (move->size < size) { 00716 size = move->size; 00717 } 00718 } 00719 00720 for (move = moves; move != NULL; move = move->next) { 00721 if (move->size == size) return(1); 00722 if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { 00723 res = cuddLinearInPlace(table,(int)move->x,(int)move->y); 00724 if (!res) return(0); 00725 } 00726 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 00727 if (!res) return(0); 00728 if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { 00729 res = cuddLinearInPlace(table,(int)move->x,(int)move->y); 00730 if (!res) return(0); 00731 } 00732 } 00733 00734 return(1); 00735 00736 } /* end of ddLinearAndSiftingBackward */
static Move* ddLinearAndSiftingDown | ( | DdManager * | table, | |
int | x, | |||
int | xHigh, | |||
Move * | prevMoves | |||
) | [static] |
Function********************************************************************
Synopsis [Sifts a variable down and applies linear transformations.]
Description [Sifts a variable down and applies linear transformations. Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 593 of file cuddLinear.c.
00598 { 00599 Move *moves; 00600 Move *move; 00601 int y; 00602 int size, newsize; 00603 int R; /* upper bound on node decrease */ 00604 int limitSize; 00605 int xindex, yindex; 00606 int isolated; 00607 #ifdef DD_DEBUG 00608 int checkR; 00609 int z; 00610 int zindex; 00611 #endif 00612 00613 moves = prevMoves; 00614 /* Initialize R */ 00615 xindex = table->invperm[x]; 00616 limitSize = size = table->keys - table->isolated; 00617 R = 0; 00618 for (y = xHigh; y > x; y--) { 00619 yindex = table->invperm[y]; 00620 if (cuddTestInteract(table,xindex,yindex)) { 00621 isolated = table->vars[yindex]->ref == 1; 00622 R += table->subtables[y].keys - isolated; 00623 } 00624 } 00625 00626 y = cuddNextHigh(table,x); 00627 while (y <= xHigh && size - R < limitSize) { 00628 #ifdef DD_DEBUG 00629 checkR = 0; 00630 for (z = xHigh; z > x; z--) { 00631 zindex = table->invperm[z]; 00632 if (cuddTestInteract(table,xindex,zindex)) { 00633 isolated = table->vars[zindex]->ref == 1; 00634 checkR += table->subtables[z].keys - isolated; 00635 } 00636 } 00637 if (R != checkR) { 00638 (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); 00639 } 00640 #endif 00641 /* Update upper bound on node decrease. */ 00642 yindex = table->invperm[y]; 00643 if (cuddTestInteract(table,xindex,yindex)) { 00644 isolated = table->vars[yindex]->ref == 1; 00645 R -= table->subtables[y].keys - isolated; 00646 } 00647 size = cuddSwapInPlace(table,x,y); 00648 if (size == 0) goto ddLinearAndSiftingDownOutOfMem; 00649 newsize = cuddLinearInPlace(table,x,y); 00650 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; 00651 move = (Move *) cuddDynamicAllocNode(table); 00652 if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; 00653 move->x = x; 00654 move->y = y; 00655 move->next = moves; 00656 moves = move; 00657 move->flags = CUDD_SWAP_MOVE; 00658 if (newsize >= size) { 00659 /* Undo transformation. The transformation we apply is 00660 ** its own inverse. Hence, we just apply the transformation 00661 ** again. 00662 */ 00663 newsize = cuddLinearInPlace(table,x,y); 00664 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; 00665 if (newsize != size) { 00666 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); 00667 } 00668 } else if (cuddTestInteract(table,xindex,yindex)) { 00669 size = newsize; 00670 move->flags = CUDD_LINEAR_TRANSFORM_MOVE; 00671 ddUpdateInteractionMatrix(table,xindex,yindex); 00672 } 00673 move->size = size; 00674 if ((double) size > (double) limitSize * table->maxGrowth) break; 00675 if (size < limitSize) limitSize = size; 00676 x = y; 00677 y = cuddNextHigh(table,x); 00678 } 00679 return(moves); 00680 00681 ddLinearAndSiftingDownOutOfMem: 00682 while (moves != NULL) { 00683 move = moves->next; 00684 cuddDeallocNode(table, (DdNode *) moves); 00685 moves = move; 00686 } 00687 return((Move *) CUDD_OUT_OF_MEM); 00688 00689 } /* end of ddLinearAndSiftingDown */
Function********************************************************************
Synopsis [Sifts a variable up and applies linear transformations.]
Description [Sifts a variable up and applies linear transformations. Moves y up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]
SideEffects [None]
Definition at line 470 of file cuddLinear.c.
00475 { 00476 Move *moves; 00477 Move *move; 00478 int x; 00479 int size, newsize; 00480 int limitSize; 00481 int xindex, yindex; 00482 int isolated; 00483 int L; /* lower bound on DD size */ 00484 #ifdef DD_DEBUG 00485 int checkL; 00486 int z; 00487 int zindex; 00488 #endif 00489 00490 moves = prevMoves; 00491 yindex = table->invperm[y]; 00492 00493 /* Initialize the lower bound. 00494 ** The part of the DD below y will not change. 00495 ** The part of the DD above y that does not interact with y will not 00496 ** change. The rest may vanish in the best case, except for 00497 ** the nodes at level xLow, which will not vanish, regardless. 00498 */ 00499 limitSize = L = table->keys - table->isolated; 00500 for (x = xLow + 1; x < y; x++) { 00501 xindex = table->invperm[x]; 00502 if (cuddTestInteract(table,xindex,yindex)) { 00503 isolated = table->vars[xindex]->ref == 1; 00504 L -= table->subtables[x].keys - isolated; 00505 } 00506 } 00507 isolated = table->vars[yindex]->ref == 1; 00508 L -= table->subtables[y].keys - isolated; 00509 00510 x = cuddNextLow(table,y); 00511 while (x >= xLow && L <= limitSize) { 00512 xindex = table->invperm[x]; 00513 #ifdef DD_DEBUG 00514 checkL = table->keys - table->isolated; 00515 for (z = xLow + 1; z < y; z++) { 00516 zindex = table->invperm[z]; 00517 if (cuddTestInteract(table,zindex,yindex)) { 00518 isolated = table->vars[zindex]->ref == 1; 00519 checkL -= table->subtables[z].keys - isolated; 00520 } 00521 } 00522 isolated = table->vars[yindex]->ref == 1; 00523 checkL -= table->subtables[y].keys - isolated; 00524 if (L != checkL) { 00525 (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); 00526 } 00527 #endif 00528 size = cuddSwapInPlace(table,x,y); 00529 if (size == 0) goto ddLinearAndSiftingUpOutOfMem; 00530 newsize = cuddLinearInPlace(table,x,y); 00531 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; 00532 move = (Move *) cuddDynamicAllocNode(table); 00533 if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; 00534 move->x = x; 00535 move->y = y; 00536 move->next = moves; 00537 moves = move; 00538 move->flags = CUDD_SWAP_MOVE; 00539 if (newsize >= size) { 00540 /* Undo transformation. The transformation we apply is 00541 ** its own inverse. Hence, we just apply the transformation 00542 ** again. 00543 */ 00544 newsize = cuddLinearInPlace(table,x,y); 00545 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; 00546 #ifdef DD_DEBUG 00547 if (newsize != size) { 00548 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); 00549 } 00550 #endif 00551 } else if (cuddTestInteract(table,xindex,yindex)) { 00552 size = newsize; 00553 move->flags = CUDD_LINEAR_TRANSFORM_MOVE; 00554 ddUpdateInteractionMatrix(table,xindex,yindex); 00555 } 00556 move->size = size; 00557 /* Update the lower bound. */ 00558 if (cuddTestInteract(table,xindex,yindex)) { 00559 isolated = table->vars[xindex]->ref == 1; 00560 L += table->subtables[y].keys - isolated; 00561 } 00562 if ((double) size > (double) limitSize * table->maxGrowth) break; 00563 if (size < limitSize) limitSize = size; 00564 y = x; 00565 x = cuddNextLow(table,y); 00566 } 00567 return(moves); 00568 00569 ddLinearAndSiftingUpOutOfMem: 00570 while (moves != NULL) { 00571 move = moves->next; 00572 cuddDeallocNode(table, (DdNode *) moves); 00573 moves = move; 00574 } 00575 return((Move *) CUDD_OUT_OF_MEM); 00576 00577 } /* end of ddLinearAndSiftingUp */
static int ddLinearUniqueCompare | ( | int * | ptrX, | |
int * | ptrY | |||
) | [static] |
Function********************************************************************
Synopsis [Comparison function used by qsort.]
Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]
SideEffects [None]
Definition at line 336 of file cuddLinear.c.
Function********************************************************************
Synopsis [Given a set of moves, returns the DD heap to the order in effect before the moves.]
Description [Given a set of moves, returns the DD heap to the order in effect before the moves. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
Definition at line 752 of file cuddLinear.c.
00755 { 00756 Move *invmoves = NULL; 00757 Move *move; 00758 Move *invmove; 00759 int size; 00760 00761 for (move = moves; move != NULL; move = move->next) { 00762 invmove = (Move *) cuddDynamicAllocNode(table); 00763 if (invmove == NULL) goto ddUndoMovesOutOfMem; 00764 invmove->x = move->x; 00765 invmove->y = move->y; 00766 invmove->next = invmoves; 00767 invmoves = invmove; 00768 if (move->flags == CUDD_SWAP_MOVE) { 00769 invmove->flags = CUDD_SWAP_MOVE; 00770 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 00771 if (!size) goto ddUndoMovesOutOfMem; 00772 } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { 00773 invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; 00774 size = cuddLinearInPlace(table,(int)move->x,(int)move->y); 00775 if (!size) goto ddUndoMovesOutOfMem; 00776 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 00777 if (!size) goto ddUndoMovesOutOfMem; 00778 } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ 00779 #ifdef DD_DEBUG 00780 (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); 00781 #endif 00782 invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; 00783 size = cuddSwapInPlace(table,(int)move->x,(int)move->y); 00784 if (!size) goto ddUndoMovesOutOfMem; 00785 size = cuddLinearInPlace(table,(int)move->x,(int)move->y); 00786 if (!size) goto ddUndoMovesOutOfMem; 00787 } 00788 invmove->size = size; 00789 } 00790 00791 return(invmoves); 00792 00793 ddUndoMovesOutOfMem: 00794 while (invmoves != NULL) { 00795 move = invmoves->next; 00796 cuddDeallocNode(table, (DdNode *) invmoves); 00797 invmoves = move; 00798 } 00799 return((Move *) CUDD_OUT_OF_MEM); 00800 00801 } /* end of ddUndoMoves */
static void ddUpdateInteractionMatrix | ( | DdManager * | table, | |
int | xindex, | |||
int | yindex | |||
) | [static] |
Function********************************************************************
Synopsis [Updates the interaction matrix.]
Description []
SideEffects [none]
SeeAlso []
Definition at line 1169 of file cuddLinear.c.
01173 { 01174 int i; 01175 for (i = 0; i < yindex; i++) { 01176 if (i != xindex && cuddTestInteract(table,i,yindex)) { 01177 if (i < xindex) { 01178 cuddSetInteract(table,i,xindex); 01179 } else { 01180 cuddSetInteract(table,xindex,i); 01181 } 01182 } 01183 } 01184 for (i = yindex+1; i < table->size; i++) { 01185 if (i != xindex && cuddTestInteract(table,yindex,i)) { 01186 if (i < xindex) { 01187 cuddSetInteract(table,i,xindex); 01188 } else { 01189 cuddSetInteract(table,xindex,i); 01190 } 01191 } 01192 } 01193 01194 } /* end of ddUpdateInteractionMatrix */
char rcsid [] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $" [static] |
Definition at line 68 of file cuddLinear.c.
int* entry [static] |
Definition at line 71 of file cuddLinear.c.