00001
00036 #include "calPortInt.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 typedef struct CalBddGenStruct CalBddGen_t;
00047
00048
00049
00050
00051 typedef enum {
00052 bdd_gen_cubes,
00053 bdd_gen_nodes
00054 } bdd_gen_type;
00055
00056
00057
00058
00059
00060 struct CalBddGenStruct {
00061 Cal_BddManager manager;
00062 bdd_gen_status status;
00063 bdd_gen_type type;
00064 union {
00065 struct {
00066 array_t *cube;
00067 } cubes;
00068 struct {
00069 st_table *visited;
00070 } nodes;
00071 } gen;
00072 struct {
00073 int sp;
00074 CalBddNode_t **nodeStack;
00075 int *idStack;
00076 } stack;
00077 CalBddNode_t *node;
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00095
00096
00097
00098 static void pop_node_stack(CalBddGen_t *gen);
00099 static void push_node_stack(Cal_Bdd_t f, CalBddGen_t *gen);
00100 static void pop_cube_stack(CalBddGen_t *gen);
00101 static void push_cube_stack(Cal_Bdd_t f, CalBddGen_t *gen);
00102
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 bdd_gen_status
00124 bdd_gen_read_status(bdd_gen *gen)
00125 {
00126 return ((CalBddGen_t *)gen)->status;
00127 }
00128
00142 bdd_gen *
00143 bdd_first_cube(bdd_t *fn,array_t **cube)
00144 {
00145 Cal_BddManager_t *manager;
00146 CalBddGen_t *gen;
00147 int i;
00148 long numVars;
00149 Cal_Bdd function;
00150 Cal_Bdd_t calBdd;
00151
00152 if (fn == NIL(bdd_t)) {
00153 CalBddFatalMessage("bdd_first_cube: invalid BDD");
00154 }
00155
00156 manager = fn->bddManager;
00157 function = fn->calBdd;
00158
00159
00160
00161
00162
00163 gen = ALLOC(CalBddGen_t, 1);
00164
00165
00166
00167
00168 gen->manager = manager;
00169 gen->status = bdd_EMPTY;
00170 gen->type = bdd_gen_cubes;
00171 gen->gen.cubes.cube = NIL(array_t);
00172 gen->stack.sp = 0;
00173 gen->stack.nodeStack = NIL(CalBddNode_t *);
00174 gen->stack.idStack = NIL(int);
00175 gen->node = NIL(CalBddNode_t);
00176
00177 numVars = Cal_BddVars(manager);
00178 gen->gen.cubes.cube = array_alloc(bdd_literal, numVars);
00179
00180
00181
00182
00183 for (i = 0; i < numVars; i++) {
00184 array_insert(bdd_literal, gen->gen.cubes.cube, i, 2);
00185 }
00186
00187
00188
00189
00190
00191
00192 gen->stack.sp = 0;
00193 gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
00194 gen->stack.idStack = ALLOC(int, numVars);
00195
00196
00197
00198
00199
00200 for (i = 0; i < numVars; i++) {
00201 gen->stack.nodeStack[i] = NIL(CalBddNode_t);
00202 gen->stack.idStack[i] = -1;
00203 }
00204
00205 if (Cal_BddIsBddZero(manager, function)){
00206
00207
00208
00209
00210
00211
00212 gen->status = bdd_EMPTY;
00213 } else {
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 gen->status = bdd_NONEMPTY;
00225 calBdd = CalBddGetInternalBdd(manager, function);
00226 push_cube_stack(calBdd, gen);
00227 }
00228 *cube = gen->gen.cubes.cube;
00229 return (bdd_gen *)(gen);
00230 }
00231
00244 boolean
00245 bdd_next_cube(bdd_gen *gen_, array_t **cube)
00246 {
00247 CalBddGen_t *gen = (CalBddGen_t *) gen_;
00248 pop_cube_stack(gen);
00249 if (gen->status == bdd_EMPTY) {
00250 return (FALSE);
00251 }
00252 *cube = gen->gen.cubes.cube;
00253 return (TRUE);
00254 }
00255
00256 bdd_gen *
00257 bdd_first_disjoint_cube(bdd_t *fn,array_t **cube)
00258 {
00259 return(bdd_first_cube(fn,cube));
00260 }
00261
00262 boolean
00263 bdd_next_disjoint_cube(bdd_gen *gen_, array_t **cube)
00264 {
00265 return(bdd_next_cube(gen_,cube));
00266 }
00267
00280 bdd_gen *
00281 bdd_first_node(bdd_t *fn, bdd_node **node)
00282 {
00283 Cal_BddManager_t *manager;
00284 CalBddGen_t *gen;
00285 long numVars;
00286 int i;
00287 Cal_Bdd_t calBdd;
00288 Cal_Bdd function;
00289
00290 if (fn == NIL(bdd_t)) {
00291 CalBddFatalMessage("bdd_first_node: invalid BDD");
00292 }
00293
00294 manager = fn->bddManager;
00295 function = fn->calBdd;
00296
00297
00298
00299
00300
00301
00302 gen = ALLOC(CalBddGen_t, 1);
00303
00304
00305
00306
00307 gen->manager = manager;
00308 gen->status = bdd_NONEMPTY;
00309 gen->type = bdd_gen_nodes;
00310 gen->gen.nodes.visited = NIL(st_table);
00311 gen->stack.sp = 0;
00312 gen->stack.nodeStack = NIL(CalBddNode_t *);
00313 gen->stack.idStack = NIL(int);
00314 gen->node = NIL(CalBddNode_t);
00315
00316
00317
00318
00319
00320 gen->gen.nodes.visited = st_init_table(st_ptrcmp, st_ptrhash);
00321
00322
00323
00324
00325
00326
00327 gen->stack.sp = 0;
00328 numVars = Cal_BddVars(manager);
00329 gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
00330 gen->stack.idStack = ALLOC(int, numVars);
00331
00332
00333
00334
00335 for (i = 0; i < numVars; i++) {
00336 gen->stack.nodeStack[i] = NIL(CalBddNode_t);
00337 gen->stack.idStack[i] = -1;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 calBdd = CalBddGetInternalBdd(manager, function);
00347 push_node_stack(calBdd, gen);
00348 gen->status = bdd_NONEMPTY;
00349
00350 *node = (bdd_node *)gen->node;
00351 return (bdd_gen *)(gen);
00352 }
00353
00366 boolean
00367 bdd_next_node(bdd_gen *gen_,bdd_node **node)
00368 {
00369 CalBddGen_t *gen = (CalBddGen_t *) gen_;
00370 pop_node_stack(gen);
00371 if (gen->status == bdd_EMPTY) {
00372 return (FALSE);
00373 }
00374 *node = (bdd_node *) gen->node;
00375 return (TRUE);
00376 }
00377
00391 int
00392 bdd_gen_free(bdd_gen *gen_)
00393 {
00394 CalBddGen_t *gen = (CalBddGen_t *) gen_;
00395 st_table *visited_table;
00396
00397 switch (gen->type) {
00398 case bdd_gen_cubes:
00399 array_free(gen->gen.cubes.cube);
00400 gen->gen.cubes.cube = NIL(array_t);
00401 break;
00402 case bdd_gen_nodes:
00403 visited_table = gen->gen.nodes.visited;
00404 st_free_table(visited_table);
00405 visited_table = NIL(st_table);
00406 break;
00407 }
00408 FREE(gen->stack.nodeStack);
00409 FREE(gen->stack.idStack);
00410 FREE(gen);
00411 return (0);
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00447 static void
00448 push_cube_stack(Cal_Bdd_t f, CalBddGen_t *gen)
00449 {
00450 bdd_variableId topId;
00451 Cal_Bdd_t f0, f1;
00452 Cal_BddManager_t *manager;
00453
00454 manager = gen->manager;
00455
00456 if (CalBddIsBddOne(manager, f)){
00457 return;
00458 }
00459
00460 topId = f.bddId-1;
00461 CalBddGetElseBdd(f, f0);
00462 CalBddGetThenBdd(f, f1);
00463
00464 if (CalBddIsBddZero(manager, f1)){
00465
00466
00467
00468
00469
00470
00471
00472
00473 array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
00474 push_cube_stack(f0, gen);
00475 }
00476 else if (CalBddIsBddZero(manager, f0)){
00477
00478
00479
00480 array_insert(bdd_literal, gen->gen.cubes.cube, topId, 1);
00481 push_cube_stack(f1, gen);
00482 } else {
00483
00484
00485
00486
00487
00488
00489
00490 gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00491 gen->stack.idStack[gen->stack.sp++] = f.bddId;
00492 array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
00493 push_cube_stack(f0, gen);
00494 }
00495 }
00496
00508 static void
00509 pop_cube_stack(CalBddGen_t *gen)
00510 {
00511 CalBddNode_t *fNode;
00512 int fId, fIndex, i;
00513 Cal_Bdd_t f1, f;
00514 Cal_BddManager_t *manager;
00515
00516 manager = gen->manager;
00517 if (gen->stack.sp == 0) {
00518
00519
00520
00521
00522 gen->status = bdd_EMPTY;
00523 } else {
00524
00525
00526
00527
00528
00529
00530 fNode = gen->stack.nodeStack[--gen->stack.sp];
00531 fId = gen->stack.idStack[gen->stack.sp];
00532 gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t);
00533
00534 gen->stack.idStack[gen->stack.sp] = -1;
00535 array_insert(bdd_literal, gen->gen.cubes.cube, fId-1, 1);
00536 fIndex = manager->idToIndex[fId];
00537 for (i = fIndex + 1; i < array_n(gen->gen.cubes.cube); i++) {
00538 array_insert(bdd_literal, gen->gen.cubes.cube,
00539 manager->indexToId[i]-1, 2);
00540 }
00541 f.bddNode = fNode;
00542 f.bddId = fId;
00543 CalBddGetThenBdd(f, f1);
00544 push_cube_stack(f1, gen);
00545 }
00546 }
00547
00567 static void
00568 push_node_stack(Cal_Bdd_t f, CalBddGen_t *gen)
00569 {
00570 Cal_Bdd_t f0, f1;
00571 bdd_node *reg_f, *reg_f0, *reg_f1;
00572
00573 reg_f = (CalBddNode_t *) CAL_BDD_POINTER(f.bddNode);
00574 if (st_is_member(gen->gen.nodes.visited, (char *) reg_f)){
00575
00576
00577
00578 return;
00579 }
00580
00581 if (CalBddIsBddConst(f)){
00582
00583
00584
00585
00586
00587
00588
00589
00590 st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
00591 gen->node = (CalBddNode_t *) reg_f;
00592 } else {
00593
00594
00595
00596
00597 CalBddGetElseBdd(f, f0);
00598 CalBddGetThenBdd(f, f1);
00599
00600 reg_f0 = (CalBddNode_t *) CAL_BDD_POINTER(f0.bddNode);
00601 reg_f1 = (CalBddNode_t *) CAL_BDD_POINTER(f1.bddNode);
00602
00603 if (st_is_member(gen->gen.nodes.visited, (char *) reg_f0) == 0){
00604
00605
00606
00607
00608
00609 gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00610 gen->stack.idStack[gen->stack.sp++] = f.bddId;
00611 push_node_stack(f0, gen);
00612 } else{
00613 if (st_is_member(gen->gen.nodes.visited, (char *) reg_f1) == 0){
00614
00615
00616
00617
00618
00619 gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00620 gen->stack.idStack[gen->stack.sp++] = f.bddId;
00621 push_node_stack(f1, gen);
00622 } else {
00623
00624
00625
00626
00627
00628
00629 st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
00630 gen->node = (CalBddNode_t *) reg_f;
00631 }
00632 }
00633 }
00634 }
00635
00648 static void
00649 pop_node_stack(CalBddGen_t *gen)
00650 {
00651 CalBddNode_t *fNode;
00652 int fId;
00653 Cal_Bdd_t calBdd;
00654
00655 if (gen->stack.sp == 0) {
00656 gen->status = bdd_EMPTY;
00657 return;
00658 }
00659 fNode = gen->stack.nodeStack[--gen->stack.sp];
00660 fId = gen->stack.idStack[gen->stack.sp];
00661 gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t);
00662 gen->stack.idStack[gen->stack.sp] = -1;
00663 calBdd.bddNode = fNode;
00664 calBdd.bddId = fId;
00665 push_node_stack(calBdd, gen);
00666 }
00667