src/cuBdd/cuddLinear.c File Reference

#include "util.h"
#include "cuddInt.h"
Include dependency graph for cuddLinear.c:

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 (int *ptrX, int *ptrY)
static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh)
static MoveddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves)
static MoveddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves)
static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves)
static MoveddUndoMoves (DdManager *table, Move *moves)
static void cuddXorLinear (DdManager *table, int x, int y)
int Cudd_PrintLinear (DdManager *table)
int Cudd_ReadLinear (DdManager *table, int x, int y)
int cuddLinearAndSifting (DdManager *table, int lower, int upper)
int cuddLinearInPlace (DdManager *table, int x, int y)
void cuddUpdateInteractionMatrix (DdManager *table, int xindex, int yindex)
int cuddInitLinear (DdManager *table)
int cuddResizeLinear (DdManager *table)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $"
static int * entry

Define Documentation

#define BPL   32

Definition at line 78 of file cuddLinear.c.

#define CUDD_INVERSE_TRANSFORM_MOVE   2

Definition at line 73 of file cuddLinear.c.

#define CUDD_LINEAR_TRANSFORM_MOVE   1

Definition at line 72 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 [Copyright (c) 1995-2004, Regents of the University of Colorado

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]

Definition at line 71 of file cuddLinear.c.

#define LOGBPL   5

Definition at line 79 of file cuddLinear.c.


Function Documentation

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 149 of file cuddLinear.c.

00151 {
00152     int i,j,k;
00153     int retval;
00154     int nvars = table->linearSize;
00155     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00156     long word;
00157 
00158     for (i = 0; i < nvars; i++) {
00159         for (j = 0; j < wordsPerRow; j++) {
00160             word = table->linear[i*wordsPerRow + j];
00161             for (k = 0; k < BPL; k++) {
00162                 retval = fprintf(table->out,"%ld",word & 1);
00163                 if (retval == 0) return(0);
00164                 word >>= 1;
00165             }
00166         }
00167         retval = fprintf(table->out,"\n");
00168         if (retval == 0) return(0);
00169     }
00170     return(1);
00171 
00172 } /* 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 187 of file cuddLinear.c.

00191 {
00192     int nvars = table->size;
00193     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00194     long word;
00195     int bit;
00196     int result;
00197 
00198     assert(table->size == table->linearSize);
00199 
00200     word = wordsPerRow * x + (y >> LOGBPL);
00201     bit  = y & (BPL-1);
00202     result = (int) ((table->linear[word] >> bit) & 1);
00203     return(result);
00204 
00205 } /* end of Cudd_ReadLinear */

int cuddInitLinear ( DdManager table  ) 

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

Synopsis [Initializes the linear transform matrix.]

Description [Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.]

SideEffects [none]

SeeAlso []

Definition at line 755 of file cuddLinear.c.

00757 {
00758     int words;
00759     int wordsPerRow;
00760     int nvars;
00761     int word;
00762     int bit;
00763     int i;
00764     long *linear;
00765 
00766     nvars = table->size;
00767     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00768     words = wordsPerRow * nvars;
00769     table->linear = linear = ALLOC(long,words);
00770     if (linear == NULL) {
00771         table->errorCode = CUDD_MEMORY_OUT;
00772         return(0);
00773     }
00774     table->memused += words * sizeof(long);
00775     table->linearSize = nvars;
00776     for (i = 0; i < words; i++) linear[i] = 0;
00777     for (i = 0; i < nvars; i++) {
00778         word = wordsPerRow * i + (i >> LOGBPL);
00779         bit  = i & (BPL-1);
00780         linear[word] = 1 << bit;
00781     }
00782     return(1);
00783 
00784 } /* 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.

  1. Order all the variables according to the number of entries in each unique table.
  2. Sift the variable up and down, remembering each time the total size of the DD heap. At each position, linear transformation of the two adjacent variables is tried and is accepted if it reduces the size of the DD.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 236 of file cuddLinear.c.

00240 {
00241     int         i;
00242     int         *var;
00243     int         size;
00244     int         x;
00245     int         result;
00246 #ifdef DD_STATS
00247     int         previousSize;
00248 #endif
00249 
00250 #ifdef DD_STATS
00251     ddTotalNumberLinearTr = 0;
00252 #endif
00253 
00254     size = table->size;
00255 
00256     var = NULL;
00257     entry = NULL;
00258     if (table->linear == NULL) {
00259         result = cuddInitLinear(table);
00260         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00261 #if 0
00262         (void) fprintf(table->out,"\n");
00263         result = Cudd_PrintLinear(table);
00264         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00265 #endif
00266     } else if (table->size != table->linearSize) {
00267         result = cuddResizeLinear(table);
00268         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00269 #if 0
00270         (void) fprintf(table->out,"\n");
00271         result = Cudd_PrintLinear(table);
00272         if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00273 #endif
00274     }
00275 
00276     /* Find order in which to sift variables. */
00277     entry = ALLOC(int,size);
00278     if (entry == NULL) {
00279         table->errorCode = CUDD_MEMORY_OUT;
00280         goto cuddLinearAndSiftingOutOfMem;
00281     }
00282     var = ALLOC(int,size);
00283     if (var == NULL) {
00284         table->errorCode = CUDD_MEMORY_OUT;
00285         goto cuddLinearAndSiftingOutOfMem;
00286     }
00287 
00288     for (i = 0; i < size; i++) {
00289         x = table->perm[i];
00290         entry[i] = table->subtables[x].keys;
00291         var[i] = i;
00292     }
00293 
00294     qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
00295 
00296     /* Now sift. */
00297     for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00298         x = table->perm[var[i]];
00299         if (x < lower || x > upper) continue;
00300 #ifdef DD_STATS
00301         previousSize = table->keys - table->isolated;
00302 #endif
00303         result = ddLinearAndSiftingAux(table,x,lower,upper);
00304         if (!result) goto cuddLinearAndSiftingOutOfMem;
00305 #ifdef DD_STATS
00306         if (table->keys < (unsigned) previousSize + table->isolated) {
00307             (void) fprintf(table->out,"-");
00308         } else if (table->keys > (unsigned) previousSize + table->isolated) {
00309             (void) fprintf(table->out,"+");     /* should never happen */
00310             (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00311         } else {
00312             (void) fprintf(table->out,"=");
00313         }
00314         fflush(table->out);
00315 #endif
00316 #ifdef DD_DEBUG
00317         (void) Cudd_DebugCheck(table);
00318 #endif
00319     }
00320 
00321     FREE(var);
00322     FREE(entry);
00323 
00324 #ifdef DD_STATS
00325     (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
00326                    ddTotalNumberLinearTr);
00327 #endif
00328 
00329     return(1);
00330 
00331 cuddLinearAndSiftingOutOfMem:
00332 
00333     if (entry != NULL) FREE(entry);
00334     if (var != NULL) FREE(var);
00335 
00336     return(0);
00337 
00338 } /* end of cuddLinearAndSifting */

int cuddLinearInPlace ( DdManager table,
int  x,
int  y 
)

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 360 of file cuddLinear.c.

00364 {
00365     DdNodePtr *xlist, *ylist;
00366     int    xindex, yindex;
00367     int    xslots, yslots;
00368     int    xshift, yshift;
00369     int    oldxkeys, oldykeys;
00370     int    newxkeys, newykeys;
00371     int    comple, newcomplement;
00372     int    i;
00373     int    posn;
00374     int    isolated;
00375     DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00376     DdNode *g,*next,*last;
00377     DdNodePtr *previousP;
00378     DdNode *tmp;
00379     DdNode *sentinel = &(table->sentinel);
00380 #ifdef DD_DEBUG
00381     int    count, idcheck;
00382 #endif
00383 
00384 #ifdef DD_DEBUG
00385     assert(x < y);
00386     assert(cuddNextHigh(table,x) == y);
00387     assert(table->subtables[x].keys != 0);
00388     assert(table->subtables[y].keys != 0);
00389     assert(table->subtables[x].dead == 0);
00390     assert(table->subtables[y].dead == 0);
00391 #endif
00392 
00393     xindex = table->invperm[x];
00394     yindex = table->invperm[y];
00395 
00396     if (cuddTestInteract(table,xindex,yindex)) {
00397 #ifdef DD_STATS
00398         ddTotalNumberLinearTr++;
00399 #endif
00400         /* Get parameters of x subtable. */
00401         xlist = table->subtables[x].nodelist;
00402         oldxkeys = table->subtables[x].keys;
00403         xslots = table->subtables[x].slots;
00404         xshift = table->subtables[x].shift;
00405 
00406         /* Get parameters of y subtable. */
00407         ylist = table->subtables[y].nodelist;
00408         oldykeys = table->subtables[y].keys;
00409         yslots = table->subtables[y].slots;
00410         yshift = table->subtables[y].shift;
00411 
00412         newxkeys = 0;
00413         newykeys = oldykeys;
00414 
00415         /* Check whether the two projection functions involved in this
00416         ** swap are isolated. At the end, we'll be able to tell how many
00417         ** isolated projection functions are there by checking only these
00418         ** two functions again. This is done to eliminate the isolated
00419         ** projection functions from the node count.
00420         */
00421         isolated = - ((table->vars[xindex]->ref == 1) +
00422                      (table->vars[yindex]->ref == 1));
00423 
00424         /* The nodes in the x layer are put in a chain.
00425         ** The chain is handled as a FIFO; g points to the beginning and
00426         ** last points to the end.
00427         */
00428         g = NULL;
00429 #ifdef DD_DEBUG
00430         last = NULL;
00431 #endif
00432         for (i = 0; i < xslots; i++) {
00433             f = xlist[i];
00434             if (f == sentinel) continue;
00435             xlist[i] = sentinel;
00436             if (g == NULL) {
00437                 g = f;
00438             } else {
00439                 last->next = f;
00440             }
00441             while ((next = f->next) != sentinel) {
00442                 f = next;
00443             } /* while there are elements in the collision chain */
00444             last = f;
00445         } /* for each slot of the x subtable */
00446 #ifdef DD_DEBUG
00447         /* last is always assigned in the for loop because there is at
00448         ** least one key */
00449         assert(last != NULL);
00450 #endif
00451         last->next = NULL;
00452 
00453 #ifdef DD_COUNT
00454         table->swapSteps += oldxkeys;
00455 #endif
00456         /* Take care of the x nodes that must be re-expressed.
00457         ** They form a linked list pointed by g.
00458         */
00459         f = g;
00460         while (f != NULL) {
00461             next = f->next;
00462             /* Find f1, f0, f11, f10, f01, f00. */
00463             f1 = cuddT(f);
00464 #ifdef DD_DEBUG
00465             assert(!(Cudd_IsComplement(f1)));
00466 #endif
00467             if ((int) f1->index == yindex) {
00468                 f11 = cuddT(f1); f10 = cuddE(f1);
00469             } else {
00470                 f11 = f10 = f1;
00471             }
00472 #ifdef DD_DEBUG
00473             assert(!(Cudd_IsComplement(f11)));
00474 #endif
00475             f0 = cuddE(f);
00476             comple = Cudd_IsComplement(f0);
00477             f0 = Cudd_Regular(f0);
00478             if ((int) f0->index == yindex) {
00479                 f01 = cuddT(f0); f00 = cuddE(f0);
00480             } else {
00481                 f01 = f00 = f0;
00482             }
00483             if (comple) {
00484                 f01 = Cudd_Not(f01);
00485                 f00 = Cudd_Not(f00);
00486             }
00487             /* Decrease ref count of f1. */
00488             cuddSatDec(f1->ref);
00489             /* Create the new T child. */
00490             if (f11 == f00) {
00491                 newf1 = f11;
00492                 cuddSatInc(newf1->ref);
00493             } else {
00494                 /* Check ylist for triple (yindex,f11,f00). */
00495                 posn = ddHash(f11, f00, yshift);
00496                 /* For each element newf1 in collision list ylist[posn]. */
00497                 previousP = &(ylist[posn]);
00498                 newf1 = *previousP;
00499                 while (f11 < cuddT(newf1)) {
00500                     previousP = &(newf1->next);
00501                     newf1 = *previousP;
00502                 }
00503                 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
00504                     previousP = &(newf1->next);
00505                     newf1 = *previousP;
00506                 }
00507                 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
00508                     cuddSatInc(newf1->ref);
00509                 } else { /* no match */
00510                     newf1 = cuddDynamicAllocNode(table);
00511                     if (newf1 == NULL)
00512                         goto cuddLinearOutOfMem;
00513                     newf1->index = yindex; newf1->ref = 1;
00514                     cuddT(newf1) = f11;
00515                     cuddE(newf1) = f00;
00516                     /* Insert newf1 in the collision list ylist[posn];
00517                     ** increase the ref counts of f11 and f00.
00518                     */
00519                     newykeys++;
00520                     newf1->next = *previousP;
00521                     *previousP = newf1;
00522                     cuddSatInc(f11->ref);
00523                     tmp = Cudd_Regular(f00);
00524                     cuddSatInc(tmp->ref);
00525                 }
00526             }
00527             cuddT(f) = newf1;
00528 #ifdef DD_DEBUG
00529             assert(!(Cudd_IsComplement(newf1)));
00530 #endif
00531 
00532             /* Do the same for f0, keeping complement dots into account. */
00533             /* decrease ref count of f0 */
00534             tmp = Cudd_Regular(f0);
00535             cuddSatDec(tmp->ref);
00536             /* create the new E child */
00537             if (f01 == f10) {
00538                 newf0 = f01;
00539                 tmp = Cudd_Regular(newf0);
00540                 cuddSatInc(tmp->ref);
00541             } else {
00542                 /* make sure f01 is regular */
00543                 newcomplement = Cudd_IsComplement(f01);
00544                 if (newcomplement) {
00545                     f01 = Cudd_Not(f01);
00546                     f10 = Cudd_Not(f10);
00547                 }
00548                 /* Check ylist for triple (yindex,f01,f10). */
00549                 posn = ddHash(f01, f10, yshift);
00550                 /* For each element newf0 in collision list ylist[posn]. */
00551                 previousP = &(ylist[posn]);
00552                 newf0 = *previousP;
00553                 while (f01 < cuddT(newf0)) {
00554                     previousP = &(newf0->next);
00555                     newf0 = *previousP;
00556                 }
00557                 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
00558                     previousP = &(newf0->next);
00559                     newf0 = *previousP;
00560                 }
00561                 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
00562                     cuddSatInc(newf0->ref);
00563                 } else { /* no match */
00564                     newf0 = cuddDynamicAllocNode(table);
00565                     if (newf0 == NULL)
00566                         goto cuddLinearOutOfMem;
00567                     newf0->index = yindex; newf0->ref = 1;
00568                     cuddT(newf0) = f01;
00569                     cuddE(newf0) = f10;
00570                     /* Insert newf0 in the collision list ylist[posn];
00571                     ** increase the ref counts of f01 and f10.
00572                     */
00573                     newykeys++;
00574                     newf0->next = *previousP;
00575                     *previousP = newf0;
00576                     cuddSatInc(f01->ref);
00577                     tmp = Cudd_Regular(f10);
00578                     cuddSatInc(tmp->ref);
00579                 }
00580                 if (newcomplement) {
00581                     newf0 = Cudd_Not(newf0);
00582                 }
00583             }
00584             cuddE(f) = newf0;
00585 
00586             /* Re-insert the modified f in xlist.
00587             ** The modified f does not already exists in xlist.
00588             ** (Because of the uniqueness of the cofactors.)
00589             */
00590             posn = ddHash(newf1, newf0, xshift);
00591             newxkeys++;
00592             previousP = &(xlist[posn]);
00593             tmp = *previousP;
00594             while (newf1 < cuddT(tmp)) {
00595                 previousP = &(tmp->next);
00596                 tmp = *previousP;
00597             }
00598             while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
00599                 previousP = &(tmp->next);
00600                 tmp = *previousP;
00601             }
00602             f->next = *previousP;
00603             *previousP = f;
00604             f = next;
00605         } /* while f != NULL */
00606 
00607         /* GC the y layer. */
00608 
00609         /* For each node f in ylist. */
00610         for (i = 0; i < yslots; i++) {
00611             previousP = &(ylist[i]);
00612             f = *previousP;
00613             while (f != sentinel) {
00614                 next = f->next;
00615                 if (f->ref == 0) {
00616                     tmp = cuddT(f);
00617                     cuddSatDec(tmp->ref);
00618                     tmp = Cudd_Regular(cuddE(f));
00619                     cuddSatDec(tmp->ref);
00620                     cuddDeallocNode(table,f);
00621                     newykeys--;
00622                 } else {
00623                     *previousP = f;
00624                     previousP = &(f->next);
00625                 }
00626                 f = next;
00627             } /* while f */
00628             *previousP = sentinel;
00629         } /* for every collision list */
00630 
00631 #ifdef DD_DEBUG
00632 #if 0
00633         (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
00634 #endif
00635         count = 0;
00636         idcheck = 0;
00637         for (i = 0; i < yslots; i++) {
00638             f = ylist[i];
00639             while (f != sentinel) {
00640                 count++;
00641                 if (f->index != (DdHalfWord) yindex)
00642                     idcheck++;
00643                 f = f->next;
00644             }
00645         }
00646         if (count != newykeys) {
00647             fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
00648         }
00649         if (idcheck != 0)
00650             fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
00651         count = 0;
00652         idcheck = 0;
00653         for (i = 0; i < xslots; i++) {
00654             f = xlist[i];
00655             while (f != sentinel) {
00656                 count++;
00657                 if (f->index != (DdHalfWord) xindex)
00658                     idcheck++;
00659                 f = f->next;
00660             }
00661         }
00662         if (count != newxkeys || newxkeys != oldxkeys) {
00663             fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
00664         }
00665         if (idcheck != 0)
00666             fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
00667 #endif
00668 
00669         isolated += (table->vars[xindex]->ref == 1) +
00670                     (table->vars[yindex]->ref == 1);
00671         table->isolated += isolated;
00672 
00673         /* Set the appropriate fields in table. */
00674         table->subtables[y].keys = newykeys;
00675 
00676         /* Here we should update the linear combination table
00677         ** to record that x <- x EXNOR y. This is done by complementing
00678         ** the (x,y) entry of the table.
00679         */
00680 
00681         table->keys += newykeys - oldykeys;
00682 
00683         cuddXorLinear(table,xindex,yindex);
00684     }
00685 
00686 #ifdef DD_DEBUG
00687     if (zero) {
00688         (void) Cudd_DebugCheck(table);
00689     }
00690 #endif
00691 
00692     return(table->keys - table->isolated);
00693 
00694 cuddLinearOutOfMem:
00695     (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
00696 
00697     return (0);
00698 
00699 } /* end of cuddLinearInPlace */

int cuddResizeLinear ( DdManager table  ) 

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

Synopsis [Resizes the linear transform matrix.]

Description [Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.]

SideEffects [none]

SeeAlso []

Definition at line 800 of file cuddLinear.c.

00802 {
00803     int words,oldWords;
00804     int wordsPerRow,oldWordsPerRow;
00805     int nvars,oldNvars;
00806     int word,oldWord;
00807     int bit;
00808     int i,j;
00809     long *linear,*oldLinear;
00810 
00811     oldNvars = table->linearSize;
00812     oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
00813     oldWords = oldWordsPerRow * oldNvars;
00814     oldLinear = table->linear;
00815 
00816     nvars = table->size;
00817     wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00818     words = wordsPerRow * nvars;
00819     table->linear = linear = ALLOC(long,words);
00820     if (linear == NULL) {
00821         table->errorCode = CUDD_MEMORY_OUT;
00822         return(0);
00823     }
00824     table->memused += (words - oldWords) * sizeof(long);
00825     for (i = 0; i < words; i++) linear[i] = 0;
00826 
00827     /* Copy old matrix. */
00828     for (i = 0; i < oldNvars; i++) {
00829         for (j = 0; j < oldWordsPerRow; j++) {
00830             oldWord = oldWordsPerRow * i + j;
00831             word = wordsPerRow * i + j;
00832             linear[word] = oldLinear[oldWord];
00833         }
00834     }
00835     FREE(oldLinear);
00836 
00837     /* Add elements to the diagonal. */
00838     for (i = oldNvars; i < nvars; i++) {
00839         word = wordsPerRow * i + (i >> LOGBPL);
00840         bit  = i & (BPL-1);
00841         linear[word] = 1 << bit;
00842     }
00843     table->linearSize = nvars;
00844 
00845     return(1);
00846 
00847 } /* end of cuddResizeLinear */

void cuddUpdateInteractionMatrix ( DdManager table,
int  xindex,
int  yindex 
)

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

Synopsis [Updates the interaction matrix.]

Description []

SideEffects [none]

SeeAlso []

Definition at line 714 of file cuddLinear.c.

00718 {
00719     int i;
00720     for (i = 0; i < yindex; i++) {
00721         if (i != xindex && cuddTestInteract(table,i,yindex)) {
00722             if (i < xindex) {
00723                 cuddSetInteract(table,i,xindex);
00724             } else {
00725                 cuddSetInteract(table,xindex,i);
00726             }
00727         }
00728     }
00729     for (i = yindex+1; i < table->size; i++) {
00730         if (i != xindex && cuddTestInteract(table,yindex,i)) {
00731             if (i < xindex) {
00732                 cuddSetInteract(table,i,xindex);
00733             } else {
00734                 cuddSetInteract(table,xindex,i);
00735             }
00736         }
00737     }
00738 
00739 } /* end of cuddUpdateInteractionMatrix */

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 1349 of file cuddLinear.c.

01353 {
01354     int i;
01355     int nvars = table->size;
01356     int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01357     int xstart = wordsPerRow * x;
01358     int ystart = wordsPerRow * y;
01359     long *linear = table->linear;
01360 
01361     for (i = 0; i < wordsPerRow; i++) {
01362         linear[xstart+i] ^= linear[ystart+i];
01363     }
01364 
01365 } /* 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 896 of file cuddLinear.c.

00901 {
00902 
00903     Move        *move;
00904     Move        *moveUp;                /* list of up moves */
00905     Move        *moveDown;              /* list of down moves */
00906     int         initialSize;
00907     int         result;
00908 
00909     initialSize = table->keys - table->isolated;
00910 
00911     moveDown = NULL;
00912     moveUp = NULL;
00913 
00914     if (x == xLow) {
00915         moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00916         /* At this point x --> xHigh unless bounding occurred. */
00917         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00918         /* Move backward and stop at best position. */
00919         result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00920         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00921 
00922     } else if (x == xHigh) {
00923         moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00924         /* At this point x --> xLow unless bounding occurred. */
00925         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00926         /* Move backward and stop at best position. */
00927         result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00928         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00929 
00930     } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
00931         moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00932         /* At this point x --> xHigh unless bounding occurred. */
00933         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00934         moveUp = ddUndoMoves(table,moveDown);
00935 #ifdef DD_DEBUG
00936         assert(moveUp == NULL || moveUp->x == x);
00937 #endif
00938         moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
00939         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00940         /* Move backward and stop at best position. */
00941         result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00942         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00943 
00944     } else { /* must go up first: shorter */
00945         moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00946         /* At this point x --> xLow unless bounding occurred. */
00947         if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00948         moveDown = ddUndoMoves(table,moveUp);
00949 #ifdef DD_DEBUG
00950         assert(moveDown == NULL || moveDown->y == x);
00951 #endif
00952         moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
00953         if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00954         /* Move backward and stop at best position. */
00955         result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00956         if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00957     }
00958 
00959     while (moveDown != NULL) {
00960         move = moveDown->next;
00961         cuddDeallocMove(table, moveDown);
00962         moveDown = move;
00963     }
00964     while (moveUp != NULL) {
00965         move = moveUp->next;
00966         cuddDeallocMove(table, moveUp);
00967         moveUp = move;
00968     }
00969 
00970     return(1);
00971 
00972 ddLinearAndSiftingAuxOutOfMem:
00973     while (moveDown != NULL) {
00974         move = moveDown->next;
00975         cuddDeallocMove(table, moveDown);
00976         moveDown = move;
00977     }
00978     while (moveUp != NULL) {
00979         move = moveUp->next;
00980         cuddDeallocMove(table, moveUp);
00981         moveUp = move;
00982     }
00983 
00984     return(0);
00985 
00986 } /* end of ddLinearAndSiftingAux */

static int ddLinearAndSiftingBackward ( DdManager table,
int  size,
Move moves 
) [static]

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 1238 of file cuddLinear.c.

01242 {
01243     Move *move;
01244     int res;
01245 
01246     for (move = moves; move != NULL; move = move->next) {
01247         if (move->size < size) {
01248             size = move->size;
01249         }
01250     }
01251 
01252     for (move = moves; move != NULL; move = move->next) {
01253         if (move->size == size) return(1);
01254         if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
01255             res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01256             if (!res) return(0);
01257         }
01258         res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01259         if (!res) return(0);
01260         if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
01261             res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01262             if (!res) return(0);
01263         }
01264     }
01265 
01266     return(1);
01267 
01268 } /* 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 1125 of file cuddLinear.c.

01130 {
01131     Move        *moves;
01132     Move        *move;
01133     int         y;
01134     int         size, newsize;
01135     int         R;      /* upper bound on node decrease */
01136     int         limitSize;
01137     int         xindex, yindex;
01138     int         isolated;
01139 #ifdef DD_DEBUG
01140     int         checkR;
01141     int         z;
01142     int         zindex;
01143 #endif
01144 
01145     moves = prevMoves;
01146     /* Initialize R */
01147     xindex = table->invperm[x];
01148     limitSize = size = table->keys - table->isolated;
01149     R = 0;
01150     for (y = xHigh; y > x; y--) {
01151         yindex = table->invperm[y];
01152         if (cuddTestInteract(table,xindex,yindex)) {
01153             isolated = table->vars[yindex]->ref == 1;
01154             R += table->subtables[y].keys - isolated;
01155         }
01156     }
01157 
01158     y = cuddNextHigh(table,x);
01159     while (y <= xHigh && size - R < limitSize) {
01160 #ifdef DD_DEBUG
01161         checkR = 0;
01162         for (z = xHigh; z > x; z--) {
01163             zindex = table->invperm[z];
01164             if (cuddTestInteract(table,xindex,zindex)) {
01165                 isolated = table->vars[zindex]->ref == 1;
01166                 checkR += table->subtables[z].keys - isolated;
01167             }
01168         }
01169         if (R != checkR) {
01170             (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
01171         }
01172 #endif
01173         /* Update upper bound on node decrease. */
01174         yindex = table->invperm[y];
01175         if (cuddTestInteract(table,xindex,yindex)) {
01176             isolated = table->vars[yindex]->ref == 1;
01177             R -= table->subtables[y].keys - isolated;
01178         }
01179         size = cuddSwapInPlace(table,x,y);
01180         if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
01181         newsize = cuddLinearInPlace(table,x,y);
01182         if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
01183         move = (Move *) cuddDynamicAllocNode(table);
01184         if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
01185         move->x = x;
01186         move->y = y;
01187         move->next = moves;
01188         moves = move;
01189         move->flags = CUDD_SWAP_MOVE;
01190         if (newsize >= size) {
01191             /* Undo transformation. The transformation we apply is
01192             ** its own inverse. Hence, we just apply the transformation
01193             ** again.
01194             */
01195             newsize = cuddLinearInPlace(table,x,y);
01196             if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
01197             if (newsize != size) {
01198                 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
01199             }
01200         } else if (cuddTestInteract(table,xindex,yindex)) {
01201             size = newsize;
01202             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01203             cuddUpdateInteractionMatrix(table,xindex,yindex);
01204         }
01205         move->size = size;
01206         if ((double) size > (double) limitSize * table->maxGrowth) break;
01207         if (size < limitSize) limitSize = size;
01208         x = y;
01209         y = cuddNextHigh(table,x);
01210     }
01211     return(moves);
01212 
01213 ddLinearAndSiftingDownOutOfMem:
01214     while (moves != NULL) {
01215         move = moves->next;
01216         cuddDeallocMove(table, moves);
01217         moves = move;
01218     }
01219     return((Move *) CUDD_OUT_OF_MEM);
01220 
01221 } /* end of ddLinearAndSiftingDown */

static Move * ddLinearAndSiftingUp ( DdManager table,
int  y,
int  xLow,
Move prevMoves 
) [static]

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 1002 of file cuddLinear.c.

01007 {
01008     Move        *moves;
01009     Move        *move;
01010     int         x;
01011     int         size, newsize;
01012     int         limitSize;
01013     int         xindex, yindex;
01014     int         isolated;
01015     int         L;      /* lower bound on DD size */
01016 #ifdef DD_DEBUG
01017     int checkL;
01018     int z;
01019     int zindex;
01020 #endif
01021 
01022     moves = prevMoves;
01023     yindex = table->invperm[y];
01024 
01025     /* Initialize the lower bound.
01026     ** The part of the DD below y will not change.
01027     ** The part of the DD above y that does not interact with y will not
01028     ** change. The rest may vanish in the best case, except for
01029     ** the nodes at level xLow, which will not vanish, regardless.
01030     */
01031     limitSize = L = table->keys - table->isolated;
01032     for (x = xLow + 1; x < y; x++) {
01033         xindex = table->invperm[x];
01034         if (cuddTestInteract(table,xindex,yindex)) {
01035             isolated = table->vars[xindex]->ref == 1;
01036             L -= table->subtables[x].keys - isolated;
01037         }
01038     }
01039     isolated = table->vars[yindex]->ref == 1;
01040     L -= table->subtables[y].keys - isolated;
01041 
01042     x = cuddNextLow(table,y);
01043     while (x >= xLow && L <= limitSize) {
01044         xindex = table->invperm[x];
01045 #ifdef DD_DEBUG
01046         checkL = table->keys - table->isolated;
01047         for (z = xLow + 1; z < y; z++) {
01048             zindex = table->invperm[z];
01049             if (cuddTestInteract(table,zindex,yindex)) {
01050                 isolated = table->vars[zindex]->ref == 1;
01051                 checkL -= table->subtables[z].keys - isolated;
01052             }
01053         }
01054         isolated = table->vars[yindex]->ref == 1;
01055         checkL -= table->subtables[y].keys - isolated;
01056         if (L != checkL) {
01057             (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
01058         }
01059 #endif
01060         size = cuddSwapInPlace(table,x,y);
01061         if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
01062         newsize = cuddLinearInPlace(table,x,y);
01063         if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
01064         move = (Move *) cuddDynamicAllocNode(table);
01065         if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
01066         move->x = x;
01067         move->y = y;
01068         move->next = moves;
01069         moves = move;
01070         move->flags = CUDD_SWAP_MOVE;
01071         if (newsize >= size) {
01072             /* Undo transformation. The transformation we apply is
01073             ** its own inverse. Hence, we just apply the transformation
01074             ** again.
01075             */
01076             newsize = cuddLinearInPlace(table,x,y);
01077             if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
01078 #ifdef DD_DEBUG
01079             if (newsize != size) {
01080                 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
01081             }
01082 #endif
01083         } else if (cuddTestInteract(table,xindex,yindex)) {
01084             size = newsize;
01085             move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01086             cuddUpdateInteractionMatrix(table,xindex,yindex);
01087         }
01088         move->size = size;
01089         /* Update the lower bound. */
01090         if (cuddTestInteract(table,xindex,yindex)) {
01091             isolated = table->vars[xindex]->ref == 1;
01092             L += table->subtables[y].keys - isolated;
01093         }
01094         if ((double) size > (double) limitSize * table->maxGrowth) break;
01095         if (size < limitSize) limitSize = size;
01096         y = x;
01097         x = cuddNextLow(table,y);
01098     }
01099     return(moves);
01100 
01101 ddLinearAndSiftingUpOutOfMem:
01102     while (moves != NULL) {
01103         move = moves->next;
01104         cuddDeallocMove(table, moves);
01105         moves = move;
01106     }
01107     return((Move *) CUDD_OUT_OF_MEM);
01108 
01109 } /* end of ddLinearAndSiftingUp */

static int ddLinearUniqueCompare ( int *  ptrX,
int *  ptrY 
) [static]

AutomaticStart

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 868 of file cuddLinear.c.

00871 {
00872 #if 0
00873     if (entry[*ptrY] == entry[*ptrX]) {
00874         return((*ptrX) - (*ptrY));
00875     }
00876 #endif
00877     return(entry[*ptrY] - entry[*ptrX]);
00878 
00879 } /* end of ddLinearUniqueCompare */

static Move * ddUndoMoves ( DdManager table,
Move moves 
) [static]

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 1284 of file cuddLinear.c.

01287 {
01288     Move *invmoves = NULL;
01289     Move *move;
01290     Move *invmove;
01291     int size;
01292 
01293     for (move = moves; move != NULL; move = move->next) {
01294         invmove = (Move *) cuddDynamicAllocNode(table);
01295         if (invmove == NULL) goto ddUndoMovesOutOfMem;
01296         invmove->x = move->x;
01297         invmove->y = move->y;
01298         invmove->next = invmoves;
01299         invmoves = invmove;
01300         if (move->flags == CUDD_SWAP_MOVE) {
01301             invmove->flags = CUDD_SWAP_MOVE;
01302             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01303             if (!size) goto ddUndoMovesOutOfMem;
01304         } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
01305             invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
01306             size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01307             if (!size) goto ddUndoMovesOutOfMem;
01308             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01309             if (!size) goto ddUndoMovesOutOfMem;
01310         } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
01311 #ifdef DD_DEBUG
01312             (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
01313 #endif
01314             invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01315             size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01316             if (!size) goto ddUndoMovesOutOfMem;
01317             size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01318             if (!size) goto ddUndoMovesOutOfMem;
01319         }
01320         invmove->size = size;
01321     }
01322 
01323     return(invmoves);
01324 
01325 ddUndoMovesOutOfMem:
01326     while (invmoves != NULL) {
01327         move = invmoves->next;
01328         cuddDeallocMove(table, invmoves);
01329         invmoves = move;
01330     }
01331     return((Move *) CUDD_OUT_OF_MEM);
01332 
01333 } /* end of ddUndoMoves */


Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $" [static]

Definition at line 95 of file cuddLinear.c.

int* entry [static]

Definition at line 98 of file cuddLinear.c.


Generated on Tue Jan 12 13:57:20 2010 for glu-2.2 by  doxygen 1.6.1