00001 #include "mdd.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 int
00019 integer_get_num_of_digits(int value)
00020 {
00021 double x;
00022 int num_of_digits;
00023
00024 if (value > 0) x = log10((double) value);
00025 else if (value == 0) x = 0;
00026 else fail("mdd_init: internal error, value less than 0\n");
00027
00028
00029
00030
00031
00032
00033 num_of_digits = (int) floor(x) + 1;
00034
00035 return num_of_digits;
00036 }
00037
00038 static void
00039 mdd_name_variables(
00040 array_t *mvar_list,
00041 int no_mvars,
00042 array_t **mvar_names_ptr)
00043 {
00044
00045 char *istr;
00046 int i;
00047
00048 if (*mvar_names_ptr == NIL(array_t)) {
00049
00050
00051 *mvar_names_ptr = array_alloc(char *, 0);
00052 for (i=0; i<no_mvars; i++) {
00053
00054 istr = ALLOC(char, integer_get_num_of_digits(i + array_n(mvar_list)) + 4);
00055 sprintf(istr, "mv_%d", (i + array_n(mvar_list)));
00056 array_insert_last(char *, *mvar_names_ptr, istr);
00057
00058 }
00059 }
00060 else {
00061 if (no_mvars != array_n(*mvar_names_ptr))
00062 fail("mdd_init: inconsistent size of mvar_names\n");
00063 }
00064 }
00065
00066
00067 static void
00068 mdd_record_variables(
00069 mdd_manager *mgr,
00070 int current_vertex_before,
00071 int start_mvar,
00072 int no_mvars,
00073 array_t *mvar_names,
00074 array_t *mvar_values,
00075 array_t *mvar_strides)
00076 {
00077
00078 array_t *mvar_list = mdd_ret_mvar_list(mgr);
00079 array_t *bvar_list = mdd_ret_bvar_list(mgr);
00080 int stride_count = 1;
00081 int prev_stride = -1;
00082 int current_vertex = current_vertex_before;
00083 int stride, i, j,
00084 bits, n_bytes;
00085 mvar_type mv;
00086 bvar_type bv;
00087 char *name_str, *mv_name;
00088
00089 #if MDD_VERBOSE
00090 printf("bdd variable insertion ordering: ");
00091 #endif
00092
00093
00094 for (i=0; i<no_mvars; i++) {
00095 mv.mvar_id = start_mvar + i;
00096
00097
00098 name_str = array_fetch(char *, mvar_names, i);
00099 n_bytes = strlen (name_str) + 1;
00100 mv_name = ALLOC(char, n_bytes);
00101 strcpy(mv_name, name_str);
00102 mv.name = mv_name;
00103
00104
00105 mv.values = array_fetch(int, mvar_values, i);
00106
00107
00108 bits = no_bit_encode(mv.values);
00109 mv.encode_length = bits;
00110
00111
00112 mv.bvars = array_alloc(int, 0);
00113
00114 if (bits > 0)
00115 stride = array_fetch(int, mvar_strides, i);
00116 else
00117 stride = 1;
00118 for(j=0; j<bits; j++) array_insert_last(int, mv.bvars, current_vertex + (j * stride) );
00119
00120
00121
00122 mv.encoding = ALLOC(int, bits);
00123
00124
00125 for (j=0; j<bits; j++) {
00126 bv.node = bdd_get_variable(mgr, current_vertex + stride*j);
00127 bv.mvar_id = mv.mvar_id;
00128
00129 #if MDD_VERBOSE
00130 printf("%d ", current_vertex + stride*j);
00131 #endif
00132
00133 array_insert(bvar_type, bvar_list, current_vertex + stride*j, bv);
00134 }
00135
00136
00137 mv.status = MDD_ACTIVE;
00138 array_insert_last(mvar_type, mvar_list, mv);
00139
00140 if ((prev_stride != -1 ) && (stride != prev_stride)) {
00141 printf("mdd_record_variables: processing %s\n", mv.name);
00142 fail("mdd_record_variables: inconsistency found in mvar_stride\n");
00143 }
00144
00145
00146
00147 if (stride_count == stride) {
00148 stride_count = 1;
00149 current_vertex = current_vertex + stride*(bits-1) + 1;
00150 prev_stride = -1;
00151 }
00152 else {
00153 stride_count++;
00154 current_vertex++;
00155 prev_stride = stride;
00156 }
00157 }
00158
00159 #if MDD_VERBOSE
00160 printf("\n");
00161 #endif
00162
00163
00164 clear_all_marks(mgr);
00165
00166 #if MONITOR
00167 print_mvar_list(mgr);
00168 (void) printf("%d bdd variables created\n", array_n(bvar_list));
00169 print_bvar_list_id(mgr);
00170 #endif
00171
00172 }
00173
00174
00175 mdd_manager *
00176 mdd_init(
00177 array_t *mvar_values,
00178 array_t *mvar_names,
00179 array_t *mvar_strides)
00180 {
00181 array_t *mvar_list;
00182 array_t *bvar_list;
00183 int i, no_mvars, current_vertex;
00184 int vertex_sum;
00185 mdd_manager *mgr;
00186 mdd_hook_type *mdd_hook;
00187 bdd_external_hooks *hook;
00188 boolean free_mvar_strides_flag;
00189 boolean free_mvar_names_flag;
00190
00191 mdd_hook = ALLOC(mdd_hook_type, 1);
00192
00193
00194 mvar_list = array_alloc(mvar_type, 0);
00195
00196
00197 bvar_list = array_alloc(bvar_type, 0);
00198
00199
00200 mdd_hook->mvar_list = mvar_list;
00201 mdd_hook->bvar_list = bvar_list;
00202
00203
00204 no_mvars = array_n(mvar_values);
00205
00206 free_mvar_names_flag = (mvar_names == NIL(array_t));
00207 mdd_name_variables(mvar_list, no_mvars, &mvar_names);
00208
00209
00210 vertex_sum = 0;
00211 for (i=0; i<no_mvars; i++) {
00212 vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
00213 }
00214 mgr = bdd_start(vertex_sum);
00215
00216 hook = bdd_get_external_hooks(mgr);
00217
00218 hook->mdd = (char *) mdd_hook;
00219
00220 current_vertex = 0;
00221
00222 if (mvar_strides == NIL(array_t)) {
00223
00224
00225
00226 free_mvar_strides_flag = TRUE;
00227 mvar_strides = array_alloc(int, 0);
00228 for (i=0; i<no_mvars; i++) {
00229 array_insert_last(int, mvar_strides, 1);
00230 }
00231 }
00232 else {
00233 free_mvar_strides_flag = FALSE;
00234 if (no_mvars != array_n(mvar_strides))
00235 fail("mdd_init: inconsistent size of mvar_strides\n");
00236 }
00237
00238
00239 mdd_record_variables(mgr, current_vertex, 0, no_mvars, mvar_names, mvar_values, mvar_strides);
00240
00241 if (free_mvar_strides_flag) {
00242 array_free(mvar_strides);
00243 }
00244
00245 if (free_mvar_names_flag) {
00246 for (i = 0; i < array_n(mvar_names); i++) {
00247 char *name = array_fetch(char *, mvar_names, i);
00248 FREE(name);
00249 }
00250 array_free(mvar_names);
00251 }
00252
00253 return mgr;
00254 }
00255
00256
00257 unsigned int
00258 mdd_create_variables(
00259 mdd_manager *mgr,
00260 array_t *mvar_values,
00261 array_t *mvar_names,
00262 array_t *mvar_strides)
00263 {
00264 array_t *mvar_list = mdd_ret_mvar_list(mgr);
00265 array_t *bvar_list = mdd_ret_bvar_list(mgr);
00266 int i, no_mvars, current_vertex, start_mvar;
00267 int vertex_sum;
00268 bdd_t *temp;
00269 boolean free_mvar_strides_flag;
00270 boolean free_mvar_names_flag;
00271
00272
00273
00274 no_mvars = array_n(mvar_values);
00275
00276 free_mvar_names_flag = (mvar_names == NIL(array_t));
00277 mdd_name_variables(mvar_list, no_mvars, &mvar_names);
00278
00279 if (mvar_strides == NIL(array_t)) {
00280
00281
00282
00283 free_mvar_strides_flag = TRUE;
00284 mvar_strides = array_alloc(int, 0);
00285 for (i=0; i<no_mvars; i++) {
00286 array_insert_last(int, mvar_strides, 1);
00287 }
00288 }
00289 else {
00290 free_mvar_strides_flag = FALSE;
00291 if (no_mvars != array_n(mvar_strides))
00292 fail("mdd_init: inconsistent size of mvar_strides\n");
00293 }
00294
00295 vertex_sum = 0;
00296 for (i=0; i<no_mvars; i++) {
00297 vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
00298 }
00299 current_vertex = array_n(bvar_list);
00300 for (i=0; i<vertex_sum; i++) {
00301 temp = bdd_get_variable(mgr, i+current_vertex);
00302 bdd_free(temp);
00303 }
00304
00305 start_mvar = array_n(mvar_list);
00306
00307 mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
00308
00309 if (free_mvar_strides_flag) {
00310 array_free(mvar_strides);
00311 }
00312
00313 if (free_mvar_names_flag) {
00314 for (i = 0; i < array_n(mvar_names); i++) {
00315 char *name = array_fetch(char *, mvar_names, i);
00316 FREE(name);
00317 }
00318 array_free(mvar_names);
00319 }
00320
00321 return start_mvar;
00322 }
00323
00324
00325 unsigned int
00326 mdd_create_variables_after(
00327 mdd_manager *mgr,
00328 int after_mvar_id,
00329 array_t *mvar_values,
00330 array_t *mvar_names,
00331 array_t *mvar_strides)
00332 {
00333 array_t *mvar_list = mdd_ret_mvar_list(mgr);
00334 array_t *bvar_list = mdd_ret_bvar_list(mgr);
00335 mvar_type after_mv, fol_mv;
00336 int i, no_mvars, current_vertex, start_mvar;
00337 int vertex_sum;
00338 int after_bv_id;
00339 bdd_t *temp;
00340 bvar_type sec_bit_of_mv;
00341 int sec_bit_level, fol_id;
00342 boolean free_mvar_strides_flag;
00343 boolean free_mvar_names_flag;
00344
00345 after_mv = array_fetch( mvar_type, mvar_list, after_mvar_id );
00346
00347 if (after_mv.encode_length > 1) {
00348 sec_bit_of_mv = mdd_ret_bvar(&after_mv, 1, bvar_list);
00349 sec_bit_level = bdd_top_var_level( mgr, sec_bit_of_mv.node );
00350
00351 fol_id = bdd_get_id_from_level( mgr, sec_bit_level - 1 );
00352 }
00353 else
00354 fol_id = mdd_ret_bvar_id(&after_mv, 0);
00355
00356 fol_mv = array_fetch( mvar_type, mvar_list, fol_id );
00357
00358 after_bv_id = mdd_ret_bvar_id(&fol_mv, fol_mv.encode_length - 1);
00359
00360
00361 no_mvars = array_n(mvar_values);
00362
00363 free_mvar_names_flag = (mvar_names == NIL(array_t));
00364 mdd_name_variables(mvar_list, no_mvars, &mvar_names);
00365
00366 if (mvar_strides == NIL(array_t)) {
00367
00368
00369
00370 free_mvar_strides_flag = TRUE;
00371 mvar_strides = array_alloc(int, 0);
00372 for (i=0; i<no_mvars; i++) {
00373 array_insert_last(int, mvar_strides, 1);
00374 }
00375 }
00376 else {
00377 free_mvar_strides_flag = FALSE;
00378 if (no_mvars != array_n(mvar_strides))
00379 fail("mdd_init: inconsistent size of mvar_strides\n");
00380 }
00381
00382 vertex_sum = 0;
00383 for (i=0; i<no_mvars; i++) {
00384 vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
00385 }
00386 for (i=0; i<vertex_sum; i++) {
00387 temp = bdd_create_variable_after(mgr, after_bv_id + i);
00388 bdd_free(temp);
00389 }
00390
00391 current_vertex = array_n(bvar_list);
00392 start_mvar = array_n(mvar_list);
00393
00394 mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
00395
00396 if (free_mvar_strides_flag) {
00397 array_free(mvar_strides);
00398 }
00399
00400 if (free_mvar_names_flag) {
00401 for (i = 0; i < array_n(mvar_names); i++) {
00402 char *name = array_fetch(char *, mvar_names, i);
00403 FREE(name);
00404 }
00405 array_free(mvar_names);
00406 }
00407
00408 return start_mvar;
00409
00410 }
00411
00412
00413 unsigned int
00414 mdd_create_variables_interleaved(
00415 mdd_manager *mgr,
00416 int inter_var_id,
00417 int no_mvars,
00418 array_t *mvar_names)
00419 {
00420 array_t *mvar_list = mdd_ret_mvar_list(mgr);
00421 array_t *bvar_list = mdd_ret_bvar_list(mgr);
00422 mvar_type inter_var;
00423 int i, j, current_vertex, start_mvar;
00424 bdd_t *temp;
00425 array_t *mvar_values;
00426 array_t *mvar_strides;
00427 boolean free_mvar_names_flag;
00428
00429 inter_var = array_fetch( mvar_type, mvar_list, inter_var_id );
00430
00431
00432 free_mvar_names_flag = (mvar_names == NIL(array_t));
00433 mdd_name_variables(mvar_list, no_mvars, &mvar_names);
00434
00435
00436 for (j=0; j<inter_var.encode_length; j++) {
00437 for (i=0; i<no_mvars; i++) {
00438 temp = bdd_create_variable_after( mgr, mdd_ret_bvar_id(&inter_var, j) );
00439 bdd_free( temp );
00440 }
00441 }
00442
00443 current_vertex = array_n(bvar_list);
00444 start_mvar = array_n(mvar_list);
00445
00446 mvar_values = array_alloc(int, 0);
00447 mvar_strides = array_alloc(int, 0);
00448 for(i=0; i<no_mvars; i++) {
00449 array_insert_last(int, mvar_values, inter_var.values);
00450 array_insert_last(int, mvar_strides, no_mvars);
00451 }
00452
00453 mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
00454
00455 array_free(mvar_values);
00456 array_free(mvar_strides);
00457
00458 if (free_mvar_names_flag) {
00459 for (i = 0; i < array_n(mvar_names); i++) {
00460 char *name = array_fetch(char *, mvar_names, i);
00461 FREE(name);
00462 }
00463 array_free(mvar_names);
00464 }
00465
00466 return start_mvar;
00467 }
00468
00469
00470 void
00471 mdd_array_free(array_t *mddArray)
00472 {
00473 int i;
00474
00475 if (mddArray != NIL(array_t)) {
00476 for (i = 0; i < array_n(mddArray); i++) {
00477 mdd_t *tempMdd = array_fetch(mdd_t *, mddArray, i);
00478 mdd_free(tempMdd);
00479 }
00480 array_free(mddArray);
00481 }
00482 }
00483
00484 void
00485 mdd_array_array_free(array_t *arrayBddArray)
00486 {
00487 int i;
00488 array_t *bddArray;
00489
00490 if (arrayBddArray != NIL(array_t)) {
00491 for (i = 0; i < array_n(arrayBddArray); i++) {
00492 bddArray = array_fetch(array_t *, arrayBddArray, i);
00493 mdd_array_free(bddArray);
00494 }
00495 array_free(arrayBddArray);
00496 }
00497 }
00498
00499 array_t *
00500 mdd_array_duplicate(array_t *mddArray)
00501 {
00502 int i;
00503 int length = array_n(mddArray);
00504 array_t *result = array_alloc(mdd_t *, length);
00505 for (i = 0; i < length; i++) {
00506 mdd_t *tempMdd = array_fetch(mdd_t *, mddArray, i);
00507 array_insert(mdd_t *, result, i, mdd_dup(tempMdd));
00508 }
00509
00510 return (result);
00511 }
00512
00513
00514
00515
00516 boolean
00517 mdd_array_equal(array_t *array1, array_t *array2)
00518 {
00519 int i;
00520
00521 assert(array1 != NIL(array_t) && array2 != NIL(array_t));
00522
00523 if(array_n(array1) != array_n(array2))
00524 return FALSE;
00525
00526 for(i = 0; i < array_n(array1); i++) {
00527 mdd_t *mdd1 = array_fetch(mdd_t *, array1, i);
00528 mdd_t *mdd2 = array_fetch(mdd_t *, array2, i);
00529 if(!mdd_equal(mdd1, mdd2))
00530 return FALSE;
00531 }
00532
00533 return TRUE;
00534 }
00535
00536
00537 mdd_manager *
00538 mdd_init_empty(void)
00539 {
00540 array_t *empty_array = array_alloc(int, 0);
00541 mdd_manager *mdd_mgr = mdd_init(empty_array, NIL(array_t), NIL(array_t));
00542
00543 array_free(empty_array);
00544 return mdd_mgr;
00545 }
00546
00547
00548
00549
00550 void
00551 mdd_var_expunge_bdd_variable(
00552 mdd_manager *mgr ,
00553 int bddId ,
00554 int val
00555 )
00556 {
00557 array_t *mvar_list = mdd_ret_mvar_list(mgr);
00558 array_t *bvar_list = mdd_ret_bvar_list(mgr);
00559 array_t *bvars;
00560
00561 bvar_type bddVar;
00562 mvar_type mvVar;
00563 int position, i, id, shift, values;
00564
00565
00566 if (val != 0 && val != 1) fail("value must be either 0 or 1");
00567 if (bddId < 0 || bddId >= array_n(bvar_list)) fail("bddId out of range");
00568
00569
00570 bddVar = array_fetch(bvar_type, bvar_list, bddId);
00571 mvVar = array_fetch(mvar_type, mvar_list, bddVar.mvar_id);
00572 bvars = array_alloc(int,array_n(mvVar.bvars)-1);
00573
00574
00575 position = array_n(mvVar.bvars);
00576 arrayForEachItem(int, mvVar.bvars, i, id) {
00577 if (id != bddId)
00578 array_insert_last(int, bvars, id);
00579 else
00580 position = i;
00581 }
00582
00583 assert(position < array_n(mvVar.bvars));
00584
00585
00586 shift = (mvVar.encode_length - position - 1);
00587
00588 for (i = 0, values = 0; i < mvVar.values; i++) {
00589 values += (i >> shift) ^ ~val;
00590 }
00591
00592
00593 array_free(mvVar.bvars);
00594 mvVar.bvars = bvars;
00595 mvVar.values = values;
00596 mvVar.encode_length--;
00597 array_insert(mvar_type, mvar_list, bddVar.mvar_id, mvVar);
00598
00599
00600 bvar_type bv = array_fetch(bvar_type, bvar_list, bddId);
00601 bv.mvar_id = -1;
00602 array_insert(bvar_type, bvar_list, bddId, bv);
00603
00604 }
00605
00606
00607
00608