#include #include #include "util.h" #include "mdd.h" /* * MDD Package * * $Id: mdd_util.c,v 1.39 2009/01/18 02:24:46 fabio Exp $ * * Author: Timothy Kam * * Copyright 1992 by the Regents of the University of California. * * All rights reserved. Permission to use, copy, modify and distribute * this software is hereby granted, provided that the above copyright * notice and this permission notice appear in all copies. This software * is made available as is, with no warranties. */ static bdd_t* mddRetOnvalBdd(mdd_manager *mddMgr, int mddId); static bdd_t* mddIntRetOnvalBdd(mdd_manager *mddMgr, int valNum, int low, int hi, int level, array_t *bddVarArr); static void mddFreeBddArr(array_t *bddArr); /************************************************************************/ #define mddGetVarById( mgr, id ) \ array_fetch(mvar_type, mdd_ret_mvar_list((mgr)),(id)) int toggle(int x) { if (x == 0) return 1; else { if (x == 1) return 0; else { fail("toggle: invalid boolean value\n"); return -1; } } } int no_bit_encode(int n) { int i = 0; int j = 1; if (n < 2) return 1; /* Takes care of mv.values <= 1 */ while (j < n) { j = j * 2; i++; } return i; } void print_mvar_list(mdd_manager *mgr) { mvar_type mv; int i; int no_mvar; array_t *mvar_list = mdd_ret_mvar_list(mgr); no_mvar = array_n(mvar_list); printf("print_mvar_list:\n"); printf("id\tname\tvalues\tbits\tstride\tstart_vertex\n"); for (i=0; i "); mdd_free(child); child = bdd_else(top); print_bdd(mgr, child); (void) printf("^ "); mdd_free(top_uncomp); mdd_free(child); return; } mvar_type find_mvar_id(mdd_manager *mgr, unsigned short id) { mvar_type mv; bvar_type bv; array_t *mvar_list = mdd_ret_mvar_list(mgr); array_t *bvar_list = mdd_ret_bvar_list(mgr); if (id >= array_n(bvar_list)) fail("find_mvar_id: invalid parameter range for id\n"); bv = array_fetch(bvar_type, bvar_list, id); if ((bv.mvar_id < 0) || (bv.mvar_id >= array_n(mvar_list))) fail("find_mvar_id: bvar contains invalid mvar_id\n"); mv = array_fetch(mvar_type, mvar_list, bv.mvar_id); return mv; } void clear_all_marks(mdd_manager *mgr) { int i, j; mvar_type mv; array_t *mvar_list = mdd_ret_mvar_list(mgr); for (i=0; imdd))->mvar_list; return mvar_list; } void mdd_set_mvar_list(mdd_manager *mgr, array_t *mvar_list) { bdd_external_hooks *hook; hook = bdd_get_external_hooks(mgr); ((mdd_hook_type *)(hook->mdd))->mvar_list = mvar_list; } array_t * mdd_ret_bvar_list(mdd_manager *mgr) { bdd_external_hooks *hook; array_t *bvar_list; hook = bdd_get_external_hooks(mgr); bvar_list = ((mdd_hook_type *)(hook->mdd))->bvar_list; return bvar_list; } void mdd_set_bvar_list(mdd_manager *mgr, array_t *bvar_list) { bdd_external_hooks *hook; hook = bdd_get_external_hooks(mgr); ((mdd_hook_type *)(hook->mdd))->bvar_list = bvar_list; } int mdd_ret_bvar_id(mvar_type *mvar_ptr, int i) { return ( array_fetch(int, mvar_ptr->bvars, i) ); } bvar_type mdd_ret_bvar(mvar_type *mvar_ptr, int i, array_t *bvar_list) { int bvar_id; bvar_id = array_fetch(int, mvar_ptr->bvars, i); return array_fetch(bvar_type, bvar_list, bvar_id); } /************************************************************************/ /* Given an Mdd, returns the num of onset points. By construction of */ /* Mdd's, some points not in the range of Mdd vars may be included */ /* in the onset. These fake points must first be removed. */ /************************************************************************/ double mdd_count_onset( mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr) { bdd_t *onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd; double onsetNum; array_t *bddVarArr; int i, arrSize, mddId; arrSize = array_n( mddIdArr ); onvalBdd = bdd_one( mddMgr ); for ( i = 0 ; i < arrSize ; i++ ) { mddId = array_fetch( int, mddIdArr, i ); aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId ); tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 ); bdd_free( onvalBdd ); bdd_free( aOnvalBdd ); onvalBdd = tmpBdd; } onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 ); bdd_free( onvalBdd ); bddVarArr = mdd_id_array_to_bdd_array( mddMgr, mddIdArr ); onsetNum = bdd_count_onset( onsetBdd, bddVarArr ); bdd_free( onsetBdd ); mddFreeBddArr( bddVarArr ); return( onsetNum ); } /* mdd_count_onset */ mdd_t * mdd_onset_bdd( mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr) { bdd_t *onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd; int i, arrSize, mddId; arrSize = array_n( mddIdArr ); onvalBdd = bdd_one( mddMgr ); for ( i = 0 ; i < arrSize ; i++ ) { mddId = array_fetch( int, mddIdArr, i ); aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId ); tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 ); bdd_free( onvalBdd ); bdd_free( aOnvalBdd ); onvalBdd = tmpBdd; } onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 ); bdd_free( onvalBdd ); return( onsetBdd ); } /* mdd_onset_bdd */ int mdd_epd_count_onset( mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr, EpDouble *epd) { bdd_t *onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd; array_t *bddVarArr; int i, arrSize, mddId; int status; arrSize = array_n( mddIdArr ); onvalBdd = bdd_one( mddMgr ); for ( i = 0 ; i < arrSize ; i++ ) { mddId = array_fetch( int, mddIdArr, i ); aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId ); tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 ); bdd_free( onvalBdd ); bdd_free( aOnvalBdd ); onvalBdd = tmpBdd; } onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 ); bdd_free( onvalBdd ); bddVarArr = mdd_id_array_to_bdd_array( mddMgr, mddIdArr ); status = bdd_epd_count_onset( onsetBdd, bddVarArr, epd ); if (status) return(status); bdd_free( onsetBdd ); mddFreeBddArr( bddVarArr ); return(0); } /* mdd_epd_count_onset */ /************************************************************************/ static bdd_t* mddRetOnvalBdd( mdd_manager *mddMgr, int mddId) { bdd_t *onvalBdd; mvar_type mVar; int valNum, high; array_t *bddVarArr; mVar = mddGetVarById( mddMgr, mddId ); valNum = mVar.values; high = (int) pow( (double) 2, (double) mVar.encode_length ); assert( (valNum == 1) || ( (valNum <= high) && (valNum > high/2) )); if ( valNum == high ) onvalBdd = bdd_one( mddMgr ); else { bddVarArr = mdd_id_to_bdd_array( mddMgr, mddId ); onvalBdd = mddIntRetOnvalBdd( mddMgr, valNum, 0, high, 0, bddVarArr ); mddFreeBddArr( bddVarArr ); } return( onvalBdd ); } /* mddRetOnvalBdd */ /************************************************************************/ static bdd_t* mddIntRetOnvalBdd( mdd_manager *mddMgr, int valNum, int low, int hi, int level, array_t *bddVarArr) { int mid; bdd_t *curVar, *recBdd; bdd_t *onvalBdd = NIL(bdd_t); /* initialized for lint */ mid = (low + hi) / 2; curVar = array_fetch( bdd_t *, bddVarArr, level ); if ( valNum > mid ) { recBdd = mddIntRetOnvalBdd( mddMgr, valNum, mid, hi, level+1, bddVarArr ); onvalBdd = bdd_or( recBdd, curVar, 1, 0 ); bdd_free( recBdd ); } else if ( valNum < mid ) { recBdd = mddIntRetOnvalBdd( mddMgr, valNum, low, mid, level+1, bddVarArr ); onvalBdd = bdd_and( recBdd, curVar, 1, 0 ); bdd_free( recBdd ); } else if ( valNum == mid ) onvalBdd = bdd_not( curVar ); return( onvalBdd ); } /* mddIntRetOnvalBdd */ /************************************************************************/ /* Given an array of bdd nodes, frees the array. */ static void mddFreeBddArr(array_t *bddArr) { int i, arrSize; arrSize = array_n( bddArr ); for ( i = 0 ; i < arrSize ; i++ ) bdd_free( array_fetch( bdd_t *, bddArr, i ) ); array_free( bddArr ); } /* mddFreeBddArr */ array_t * mdd_ret_bvars_of_mvar(mvar_type *mvar_ptr) { return mvar_ptr->bvars; } /************************************************************************/ /* mdd_get_care_set returns the care set of the mdd manager */ static mdd_t *mdd_get_care_set(mdd_manager *mdd_mgr) { mdd_t *temp; mvar_type mv; mdd_manager *bdd_mgr; int mvar_id,i,j,val_j,value; array_t *mvar_list; bdd_t *care_set, *care_val, *care_cube,*bit_j; mvar_list = mdd_ret_mvar_list(mdd_mgr); bdd_mgr = mdd_mgr; care_set = bdd_one(bdd_mgr); for (mvar_id =0; mvar_id < array_n(mvar_list); mvar_id++) { mv = array_fetch(mvar_type, mvar_list, mvar_id); care_val = bdd_zero(bdd_mgr); for (i=0; i< (mv.values); i++) { value = i; care_cube = bdd_one(bdd_mgr); for(j=0; j< mv.encode_length; j++ ) { bit_j = bdd_get_variable(bdd_mgr,mdd_ret_bvar_id(&mv, j)); val_j = value % 2; value = value/2; temp = care_cube; care_cube = bdd_and(temp,bit_j,1,val_j); bdd_free(temp); } temp = care_val; care_val = bdd_or(temp,care_cube,1,1); bdd_free(temp); bdd_free(care_cube); } temp = care_set; care_set = bdd_and(temp,care_val,1,1); bdd_free(care_val); bdd_free(temp); } return care_set; } /* Corrected mdd_cproject */ /* returns only valid carepoints */ mdd_t *mdd_cproject( mdd_manager *mgr, mdd_t *T, array_t *mvars) { mdd_t *care_set, *new_T, *T_proj; array_t *bdd_vars; int i, j, mv_no; mvar_type mv; bdd_t *temp; array_t *mvar_list = mdd_ret_mvar_list(mgr); care_set = mdd_get_care_set(mgr); new_T = bdd_and(T,care_set,1,1); bdd_free(care_set); if ( mvars == NIL(array_t) ) { T_proj = bdd_dup(T); printf("\nWARNING: Empty Array of Smoothing Variables\n"); return T_proj; } else if ( array_n(mvars) == 0) { T_proj = bdd_dup(T); printf("\nWARNING: Empty Array of Smoothing Variables\n"); return T_proj; } bdd_vars = array_alloc(bdd_t*, 0); for (i=0; i= 0; i--) { if (vars[i] == 0) continue; id = (int)bdd_get_id_from_level(mddManager, (long)i); var = bdd_get_variable(mddManager, id); tmp = mdd_and(cube, var, 1, 1); mdd_free(cube); mdd_free(var); cube = tmp; } FREE(vars); return cube; } /**Function******************************************************************** Synopsis [Returns the number of bdd variables from mdd id array.] Description [Returns the number of bdd variables from mdd id array.] SideEffects [] ******************************************************************************/ int mdd_get_number_of_bdd_vars(mdd_manager *mddManager, array_t *mddIdArray) { int i, n; n = 0; for (i=0; i