extraZddTrunc.c 11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
/**CFile****************************************************************

  FileName    [extraZddTrunc.c]

  PackageName [extra]

  Synopsis    [Procedure to truncate a ZDD using variable probabilities.]

  Author      [Alan Mishchenko]

  Affiliation [UC Berkeley]

  Date        [Ver. 2.0. Started - September 1, 2003.]

  Revision    [$Id: extraZddTrunc.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]

***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "misc/st/st.h"
#include "bdd/cudd/cuddInt.h"

#ifdef _WIN32
#define inline __inline // compatible with MS VS 6.0
#endif

ABC_NAMESPACE_IMPL_START


#define TEST_VAR_MAX 10
#define TEST_SET_MAX 10

/*---------------------------------------------------------------------------*/
/* Constant declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Stucture declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Type declarations                                                         */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Variable declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Macro declarations                                                        */
/*---------------------------------------------------------------------------*/


/**AutomaticStart*************************************************************/

/*---------------------------------------------------------------------------*/
/* Static function prototypes                                                */
/*---------------------------------------------------------------------------*/


// dynamic vector of intergers
typedef struct Vec_Int_t_       Vec_Int_t;
struct Vec_Int_t_ 
{
    int              nCap;
    int              nSize;
    int *            pArray;
};
static inline Vec_Int_t * Vec_IntAlloc( int nCap )
{
    Vec_Int_t * p;
    p = ABC_ALLOC( Vec_Int_t, 1 );
    if ( nCap > 0 && nCap < 16 )
        nCap = 16;
    p->nSize  = 0;
    p->nCap   = nCap;
    p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL;
    return p;
}
static inline void Vec_IntFree( Vec_Int_t * p )
{
    ABC_FREE( p->pArray );
    ABC_FREE( p );
}
static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
{
    int * pArray = p->pArray;
    p->nCap = 0;
    p->nSize = 0;
    p->pArray = NULL;
    return pArray;
}
static inline int Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
{
    assert( i >= 0 && i < p->nSize );
    return p->pArray[i] += Addition;
}
static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
{
    if ( p->nCap >= nCapMin )
        return;
    p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); 
    assert( p->pArray );
    p->nCap   = nCapMin;
}
static inline int Vec_IntPop( Vec_Int_t * p )
{
    assert( p->nSize > 0 );
    return p->pArray[--p->nSize];
}
static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
{
    if ( p->nSize == p->nCap )
    {
        if ( p->nCap < 16 )
            Vec_IntGrow( p, 16 );
        else
            Vec_IntGrow( p, 2 * p->nCap );
    }
    p->pArray[p->nSize++] = Entry;
}
static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 )
{
    int i;
    for ( i = 0; i < vVec2->nSize; i++ )
        Vec_IntPush( vVec1, vVec2->pArray[i] );
}


/**AutomaticEnd***************************************************************/


/*---------------------------------------------------------------------------*/
/* Definition of exported functions                                          */
/*---------------------------------------------------------------------------*/

/**Function********************************************************************

  Synopsis    [Compute the set of subsets whose probability is more than ProbLimit.]

  Description [The resulting array has the following form:  The first integer entry 
  is the number of resulting subsets.  The following integer entries in the array
  contain as many subsets. Each subset is an array of integers followed by -1. 
  See how subsets are printed in the included test procedure below.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
void Extra_zddTruncate_rec(
  DdManager * dd, 
  DdNode * zFunc,       // zFunc is the ZDD to be truncated
  double * pVarProbs,    // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries)
  double ProbLimit,      // ProbLimit is the limit on the probabilities (only those more than this will be collected)
  double ProbThis,       // current path probability
  Vec_Int_t * vSubset,  // current subset under construction
  Vec_Int_t * vResult ) // resulting subsets to be returned to the user
{
    // quit if probability of the path is less then the limit
    if ( ProbThis < ProbLimit )
        return;
    // quit if there is no subsets
    if ( zFunc == Cudd_ReadZero(dd) ) 
        return;
    // quit and save a new subset if there is one
    if ( zFunc == Cudd_ReadOne(dd) ) 
    {
        Vec_IntAddToEntry( vResult, 0, 1 );
        Vec_IntAppend( vResult, vSubset );
        Vec_IntPush( vResult, -1 );
        return;
    }
    // call recursively for the set without the given variable
    Extra_zddTruncate_rec( dd, cuddE(zFunc), pVarProbs, ProbLimit, ProbThis, vSubset, vResult );
    // call recursively for the set with the given variable
    Vec_IntPush( vSubset, Cudd_NodeReadIndex(zFunc) );
    Extra_zddTruncate_rec( dd, cuddT(zFunc), pVarProbs, ProbLimit, ProbThis * pVarProbs[Cudd_NodeReadIndex(zFunc)], vSubset, vResult );
    Vec_IntPop( vSubset );
}
int * Extra_zddTruncate( 
  DdManager * dd, 
  DdNode * zFunc,       // zFunc is the ZDD to be truncated
  double * pVarProbs,    // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries)
  double ProbLimit )     // ProbLimit is the limit on the probabilities (only those more than this will be collected)
{
    Vec_Int_t * vSubset, * vResult;
    int i, sizeZ = Cudd_ReadZddSize(dd);
    int * pResult;
    // check that probabilities are reasonable
    assert( ProbLimit > 0 && ProbLimit <= 1 );
    for ( i = 0; i < sizeZ; i++ )
        assert( pVarProbs[i] > 0 && pVarProbs[i] <= 1 );
    // enumerate assignments satisfying the probability limit
    vSubset = Vec_IntAlloc( sizeZ );
    vResult = Vec_IntAlloc( 10 * sizeZ );
    Vec_IntPush( vResult, 0 );
    Extra_zddTruncate_rec( dd, zFunc, pVarProbs, ProbLimit, 1, vSubset, vResult );
    Vec_IntFree( vSubset );
    pResult = Vec_IntReleaseArray( vResult );
    Vec_IntFree( vResult );
    return pResult;
} // end of Extra_zddTruncate 

/**Function*************************************************************

  Synopsis    [Creates the combination composed of a single ZDD variable.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Extra_zddVariable( DdManager * dd, int iVar )
{
    DdNode * zRes;
    do {
        dd->reordered = 0;
        zRes = cuddZddGetNode( dd, iVar, Cudd_ReadOne(dd), Cudd_ReadZero(dd) ); 
    } while (dd->reordered == 1);
    return zRes;
}

/**Function********************************************************************

  Synopsis    [Creates ZDD representing a given set of subsets.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * Extra_zddCreateSubsets(
  DdManager * dd,
  int pSubsets[][TEST_VAR_MAX+1],
  int nSubsets )
{
    int i, k;
    DdNode * zOne, * zVar, * zRes, * zTemp;
    zRes = Cudd_ReadZero(dd); Cudd_Ref( zRes );
    for ( i = 0; i < nSubsets; i++ )
    {
        zOne = Cudd_ReadOne(dd); Cudd_Ref( zOne );
        for ( k = 0; pSubsets[i][k] != -1; k++ )
        {
            assert( pSubsets[i][k] < TEST_VAR_MAX );
            zVar = Extra_zddVariable( dd, pSubsets[i][k] );
            zOne = Cudd_zddUnateProduct( dd, zTemp = zOne, zVar ); Cudd_Ref( zOne );
            Cudd_RecursiveDerefZdd( dd, zTemp );
        }
        zRes = Cudd_zddUnion( dd, zRes, zOne ); Cudd_Ref( zRes );
        Cudd_RecursiveDerefZdd( dd, zOne );
    }
    Cudd_Deref( zRes );
    return zRes;
}

/**Function********************************************************************

  Synopsis    [Prints a set of subsets represented using as an array.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
void Extra_zddPrintSubsets( int * pSubsets )
{
    int i, k, Counter = 0;
    printf( "The set contains %d subsets:\n", pSubsets[0] );
    for ( i = k = 0; i < pSubsets[0]; i++ )
    {
        printf( "Subset %3d : {", Counter );
        for ( k++; pSubsets[k] != -1; k++ )
            printf( " %d", pSubsets[k] );
        printf( " }\n" );
        Counter++;
    }
}

/**Function********************************************************************

  Synopsis    [Testbench for the above truncation procedure.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
void Extra_zddTruncateTest()
{
    // input data
    int nSubsets = 5;
    int pSubsets[TEST_SET_MAX][TEST_VAR_MAX+1] = { {0, 3, 5, -1}, {1, 2, 3, 6, 9, -1}, {1, 5, 7, 8, -1}, {2, 4, -1}, {0, 5, 6, 9, -1} };
    // varible probabilities
    double pVarProbs[TEST_VAR_MAX] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 };
    double ProbLimit = 0.001;
    // output data
    int * pOutput;
    // start the manager and create ZDD representing the input subsets
    DdManager * dd = Cudd_Init( 0, TEST_VAR_MAX, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS , 0 );
    DdNode * zFunc = Extra_zddCreateSubsets( dd, pSubsets, nSubsets );  Cudd_Ref( zFunc );
    assert( nSubsets <= TEST_SET_MAX );
    // print the input ZDD
    printf( "The initial ZDD representing %d subsets:\n", nSubsets );
    Cudd_zddPrintMinterm( dd, zFunc );
    // compute the result of truncation
    pOutput = Extra_zddTruncate( dd, zFunc, pVarProbs, ProbLimit );
    // print the resulting ZDD
    printf( "The resulting ZDD representing %d subsets:\n", pOutput[0] );
    // print the resulting subsets
    Extra_zddPrintSubsets( pOutput );
    // cleanup
    ABC_FREE( pOutput );
    Cudd_RecursiveDerefZdd( dd, zFunc );
    Cudd_Quit( dd );
} 




////////////////////////////////////////////////////////////////////////
///                           END OF FILE                            ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END