00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "espresso.h"
00028
00029 #define USE_COMPL_LIFT 0
00030 #define USE_COMPL_LIFT_ONSET 1
00031 #define USE_COMPL_LIFT_ONSET_COMPLEX 2
00032 #define NO_LIFTING 3
00033
00034 static bool compl_special_cases();
00035 static pcover compl_merge();
00036 static void compl_d1merge();
00037 static pcover compl_cube();
00038 static void compl_lift();
00039 static void compl_lift_onset();
00040 static void compl_lift_onset_complex();
00041 static bool simp_comp_special_cases();
00042 static bool simplify_special_cases();
00043
00044
00045
00046 pcover complement(T)
00047 pcube *T;
00048 {
00049 register pcube cl, cr;
00050 register int best;
00051 pcover Tbar, Tl, Tr;
00052 int lifting;
00053 static int compl_level = 0;
00054
00055 if (debug & COMPL)
00056 debug_print(T, "COMPLEMENT", compl_level++);
00057
00058 if (compl_special_cases(T, &Tbar) == MAYBE) {
00059
00060
00061 cl = new_cube();
00062 cr = new_cube();
00063 best = binate_split_select(T, cl, cr, COMPL);
00064
00065
00066 Tl = complement(scofactor(T, cl, best));
00067 Tr = complement(scofactor(T, cr, best));
00068
00069 if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
00070 lifting = USE_COMPL_LIFT_ONSET;
00071 } else {
00072 lifting = USE_COMPL_LIFT;
00073 }
00074 Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
00075
00076 free_cube(cl);
00077 free_cube(cr);
00078 free_cubelist(T);
00079 }
00080
00081 if (debug & COMPL)
00082 debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
00083 return Tbar;
00084 }
00085
00086 static bool compl_special_cases(T, Tbar)
00087 pcube *T;
00088 pcover *Tbar;
00089 {
00090 register pcube *T1, p, ceil, cof=T[0];
00091 pcover A, ceil_compl;
00092
00093
00094 if (T[2] == NULL) {
00095 *Tbar = sf_addset(new_cover(1), cube.fullset);
00096 free_cubelist(T);
00097 return TRUE;
00098 }
00099
00100
00101 if (T[3] == NULL) {
00102 *Tbar = compl_cube(set_or(cof, cof, T[2]));
00103 free_cubelist(T);
00104 return TRUE;
00105 }
00106
00107
00108 for(T1 = T+2; (p = *T1++) != NULL; ) {
00109 if (full_row(p, cof)) {
00110 *Tbar = new_cover(0);
00111 free_cubelist(T);
00112 return TRUE;
00113 }
00114 }
00115
00116
00117 ceil = set_save(cof);
00118 for(T1 = T+2; (p = *T1++) != NULL; ) {
00119 INLINEset_or(ceil, ceil, p);
00120 }
00121 if (! setp_equal(ceil, cube.fullset)) {
00122 ceil_compl = compl_cube(ceil);
00123 (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
00124 set_free(ceil);
00125 *Tbar = sf_append(complement(T), ceil_compl);
00126 return TRUE;
00127 }
00128 set_free(ceil);
00129
00130
00131 massive_count(T);
00132
00133
00134 if (cdata.vars_active == 1) {
00135 *Tbar = new_cover(0);
00136 free_cubelist(T);
00137 return TRUE;
00138
00139
00140 } else if (cdata.vars_unate == cdata.vars_active) {
00141 A = map_cover_to_unate(T);
00142 free_cubelist(T);
00143 A = unate_compl(A);
00144 *Tbar = map_unate_to_cover(A);
00145 sf_free(A);
00146 return TRUE;
00147
00148
00149 } else {
00150 return MAYBE;
00151 }
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
00170 pcube *T1;
00171 pcover L, R;
00172 register pcube cl, cr;
00173 int var;
00174 int lifting;
00175 {
00176 register pcube p, last, pt;
00177 pcover T, Tbar;
00178 pcube *L1, *R1;
00179
00180 if (debug & COMPL) {
00181 (void) printf("compl_merge: left %d, right %d\n", L->count, R->count);
00182 (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
00183 cprint(L);
00184 (void) printf("Right is\n");
00185 cprint(R);
00186 }
00187
00188
00189 foreach_set(L, last, p) {
00190 INLINEset_and(p, p, cl);
00191 SET(p, ACTIVE);
00192 }
00193 foreach_set(R, last, p) {
00194 INLINEset_and(p, p, cr);
00195 SET(p, ACTIVE);
00196 }
00197
00198
00199 (void) set_copy(cube.temp[0], cube.var_mask[var]);
00200 qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order);
00201 qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order);
00202
00203
00204 compl_d1merge(L1, R1);
00205
00206
00207 switch(lifting) {
00208 case USE_COMPL_LIFT_ONSET:
00209 T = cubeunlist(T1);
00210 compl_lift_onset(L1, T, cr, var);
00211 compl_lift_onset(R1, T, cl, var);
00212 free_cover(T);
00213 break;
00214 case USE_COMPL_LIFT_ONSET_COMPLEX:
00215 T = cubeunlist(T1);
00216 compl_lift_onset_complex(L1, T, var);
00217 compl_lift_onset_complex(R1, T, var);
00218 free_cover(T);
00219 break;
00220 case USE_COMPL_LIFT:
00221 compl_lift(L1, R1, cr, var);
00222 compl_lift(R1, L1, cl, var);
00223 break;
00224 case NO_LIFTING:
00225 break;
00226 default:
00227 ;
00228 }
00229 FREE(L1);
00230 FREE(R1);
00231
00232
00233 Tbar = new_cover(L->count + R->count);
00234 pt = Tbar->data;
00235 foreach_set(L, last, p) {
00236 INLINEset_copy(pt, p);
00237 Tbar->count++;
00238 pt += Tbar->wsize;
00239 }
00240 foreach_active_set(R, last, p) {
00241 INLINEset_copy(pt, p);
00242 Tbar->count++;
00243 pt += Tbar->wsize;
00244 }
00245
00246 if (debug & COMPL) {
00247 (void) printf("Result %d\n", Tbar->count);
00248 if (verbose_debug)
00249 cprint(Tbar);
00250 }
00251
00252 free_cover(L);
00253 free_cover(R);
00254 return Tbar;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static void compl_lift(A1, B1, bcube, var)
00264 pcube *A1, *B1, bcube;
00265 int var;
00266 {
00267 register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
00268 pcube mask = cube.var_mask[var];
00269
00270 (void) set_and(liftor, bcube, mask);
00271
00272
00273 for(; (a = *A1++) != NULL; ) {
00274 if (TESTP(a, ACTIVE)) {
00275
00276
00277 (void) set_merge(lift, bcube, a, mask);
00278
00279
00280 for(B2 = B1; (b = *B2++) != NULL; ) {
00281 INLINEsetp_implies(lift, b, continue);
00282
00283
00284
00285 INLINEset_or(a, a, liftor);
00286 break;
00287 }
00288 }
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 static void compl_lift_onset(A1, T, bcube, var)
00301 pcube *A1;
00302 pcover T;
00303 pcube bcube;
00304 int var;
00305 {
00306 register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
00307
00308
00309 for(; (a = *A1++) != NULL; ) {
00310 if (TESTP(a, ACTIVE)) {
00311
00312
00313 INLINEset_and(lift, bcube, mask);
00314 INLINEset_or(lift, a, lift);
00315
00316
00317 foreach_set(T, last, p) {
00318 if (cdist0(p, lift)) {
00319 goto nolift;
00320 }
00321 }
00322 INLINEset_copy(a, lift);
00323 SET(a, ACTIVE);
00324 nolift : ;
00325 }
00326 }
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 static void compl_lift_onset_complex(A1, T, var)
00336 pcube *A1;
00337 pcover T;
00338 int var;
00339 {
00340 register int dist;
00341 register pcube last, p, a, xlower;
00342
00343
00344 xlower = new_cube();
00345 for(; (a = *A1++) != NULL; ) {
00346
00347 if (TESTP(a, ACTIVE)) {
00348
00349
00350 INLINEset_clear(xlower, cube.size);
00351 foreach_set(T, last, p) {
00352 if ((dist = cdist01(p, a)) < 2) {
00353 if (dist == 0) {
00354 fatal("compl: ON-set and OFF-set are not orthogonal");
00355 } else {
00356 (void) force_lower(xlower, p, a);
00357 }
00358 }
00359 }
00360
00361 (void) set_diff(xlower, cube.var_mask[var], xlower);
00362 (void) set_or(a, a, xlower);
00363 free_cube(xlower);
00364 }
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 static void compl_d1merge(L1, R1)
00374 register pcube *L1, *R1;
00375 {
00376 register pcube pl, pr;
00377
00378
00379 for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
00380 switch (d1_order(L1, R1)) {
00381 case 1:
00382 pr = *(++R1); break;
00383 case -1:
00384 pl = *(++L1); break;
00385 case 0:
00386 RESET(pr, ACTIVE);
00387 INLINEset_or(pl, pl, pr);
00388 pr = *(++R1);
00389 default:
00390 ;
00391 }
00392 }
00393
00394
00395
00396
00397 static pcover compl_cube(p)
00398 register pcube p;
00399 {
00400 register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
00401 int var;
00402 pcover R;
00403
00404
00405 R = new_cover(cube.num_vars);
00406
00407
00408 INLINEset_diff(diff, full, p);
00409
00410 for(var = 0; var < cube.num_vars; var++) {
00411 mask = cube.var_mask[var];
00412
00413 if (! setp_disjoint(diff, mask)) {
00414 pdest = GETSET(R, R->count++);
00415 INLINEset_merge(pdest, diff, full, mask);
00416 }
00417 }
00418 return R;
00419 }
00420
00421
00422 void simp_comp(T, Tnew, Tbar)
00423 pcube *T;
00424 pcover *Tnew;
00425 pcover *Tbar;
00426 {
00427 register pcube cl, cr;
00428 register int best;
00429 pcover Tl, Tr, Tlbar, Trbar;
00430 int lifting;
00431 static int simplify_level = 0;
00432
00433 if (debug & COMPL)
00434 debug_print(T, "SIMPCOMP", simplify_level++);
00435
00436 if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
00437
00438
00439 cl = new_cube();
00440 cr = new_cube();
00441 best = binate_split_select(T, cl, cr, COMPL);
00442
00443
00444 simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
00445 simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
00446
00447 lifting = USE_COMPL_LIFT;
00448 *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
00449
00450 lifting = USE_COMPL_LIFT;
00451 *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
00452
00453
00454 if ((*Tnew)->count > CUBELISTSIZE(T)) {
00455 sf_free(*Tnew);
00456 *Tnew = cubeunlist(T);
00457 }
00458
00459 free_cube(cl);
00460 free_cube(cr);
00461 free_cubelist(T);
00462 }
00463
00464 if (debug & COMPL) {
00465 debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
00466 debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
00467 simplify_level--;
00468 }
00469 }
00470
00471 static bool simp_comp_special_cases(T, Tnew, Tbar)
00472 pcube *T;
00473 pcover *Tnew;
00474 pcover *Tbar;
00475 {
00476 register pcube *T1, p, ceil, cof=T[0];
00477 pcube last;
00478 pcover A;
00479
00480
00481 if (T[2] == NULL) {
00482 *Tnew = new_cover(1);
00483 *Tbar = sf_addset(new_cover(1), cube.fullset);
00484 free_cubelist(T);
00485 return TRUE;
00486 }
00487
00488
00489 if (T[3] == NULL) {
00490 (void) set_or(cof, cof, T[2]);
00491 *Tnew = sf_addset(new_cover(1), cof);
00492 *Tbar = compl_cube(cof);
00493 free_cubelist(T);
00494 return TRUE;
00495 }
00496
00497
00498 for(T1 = T+2; (p = *T1++) != NULL; ) {
00499 if (full_row(p, cof)) {
00500 *Tnew = sf_addset(new_cover(1), cube.fullset);
00501 *Tbar = new_cover(1);
00502 free_cubelist(T);
00503 return TRUE;
00504 }
00505 }
00506
00507
00508 ceil = set_save(cof);
00509 for(T1 = T+2; (p = *T1++) != NULL; ) {
00510 INLINEset_or(ceil, ceil, p);
00511 }
00512 if (! setp_equal(ceil, cube.fullset)) {
00513 p = new_cube();
00514 (void) set_diff(p, cube.fullset, ceil);
00515 (void) set_or(cof, cof, p);
00516 set_free(p);
00517 simp_comp(T, Tnew, Tbar);
00518
00519
00520 A = *Tnew;
00521 foreach_set(A, last, p) {
00522 INLINEset_and(p, p, ceil);
00523 }
00524
00525
00526 *Tbar = sf_append(*Tbar, compl_cube(ceil));
00527 set_free(ceil);
00528 return TRUE;
00529 }
00530 set_free(ceil);
00531
00532
00533 massive_count(T);
00534
00535
00536 if (cdata.vars_active == 1) {
00537 *Tnew = sf_addset(new_cover(1), cube.fullset);
00538 *Tbar = new_cover(1);
00539 free_cubelist(T);
00540 return TRUE;
00541
00542
00543 } else if (cdata.vars_unate == cdata.vars_active) {
00544
00545 A = cubeunlist(T);
00546 *Tnew = sf_contain(A);
00547
00548
00549 A = map_cover_to_unate(T);
00550 A = unate_compl(A);
00551 *Tbar = map_unate_to_cover(A);
00552 sf_free(A);
00553 free_cubelist(T);
00554 return TRUE;
00555
00556
00557 } else {
00558 return MAYBE;
00559 }
00560 }
00561
00562
00563 pcover simplify(T)
00564 pcube *T;
00565 {
00566 register pcube cl, cr;
00567 register int best;
00568 pcover Tbar, Tl, Tr;
00569 int lifting;
00570 static int simplify_level = 0;
00571
00572 if (debug & COMPL) {
00573 debug_print(T, "SIMPLIFY", simplify_level++);
00574 }
00575
00576 if (simplify_special_cases(T, &Tbar) == MAYBE) {
00577
00578
00579 cl = new_cube();
00580 cr = new_cube();
00581
00582 best = binate_split_select(T, cl, cr, COMPL);
00583
00584
00585 Tl = simplify(scofactor(T, cl, best));
00586 Tr = simplify(scofactor(T, cr, best));
00587
00588 lifting = USE_COMPL_LIFT;
00589 Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
00590
00591
00592 if (Tbar->count > CUBELISTSIZE(T)) {
00593 sf_free(Tbar);
00594 Tbar = cubeunlist(T);
00595 }
00596
00597 free_cube(cl);
00598 free_cube(cr);
00599 free_cubelist(T);
00600 }
00601
00602 if (debug & COMPL) {
00603 debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
00604 }
00605 return Tbar;
00606 }
00607
00608 static bool simplify_special_cases(T, Tnew)
00609 pcube *T;
00610 pcover *Tnew;
00611 {
00612 register pcube *T1, p, ceil, cof=T[0];
00613 pcube last;
00614 pcover A;
00615
00616
00617 if (T[2] == NULL) {
00618 *Tnew = new_cover(0);
00619 free_cubelist(T);
00620 return TRUE;
00621 }
00622
00623
00624 if (T[3] == NULL) {
00625 *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
00626 free_cubelist(T);
00627 return TRUE;
00628 }
00629
00630
00631 for(T1 = T+2; (p = *T1++) != NULL; ) {
00632 if (full_row(p, cof)) {
00633 *Tnew = sf_addset(new_cover(1), cube.fullset);
00634 free_cubelist(T);
00635 return TRUE;
00636 }
00637 }
00638
00639
00640 ceil = set_save(cof);
00641 for(T1 = T+2; (p = *T1++) != NULL; ) {
00642 INLINEset_or(ceil, ceil, p);
00643 }
00644 if (! setp_equal(ceil, cube.fullset)) {
00645 p = new_cube();
00646 (void) set_diff(p, cube.fullset, ceil);
00647 (void) set_or(cof, cof, p);
00648 free_cube(p);
00649
00650 A = simplify(T);
00651 foreach_set(A, last, p) {
00652 INLINEset_and(p, p, ceil);
00653 }
00654 *Tnew = A;
00655 set_free(ceil);
00656 return TRUE;
00657 }
00658 set_free(ceil);
00659
00660
00661 massive_count(T);
00662
00663
00664 if (cdata.vars_active == 1) {
00665 *Tnew = sf_addset(new_cover(1), cube.fullset);
00666 free_cubelist(T);
00667 return TRUE;
00668
00669
00670 } else if (cdata.vars_unate == cdata.vars_active) {
00671 A = cubeunlist(T);
00672 *Tnew = sf_contain(A);
00673 free_cubelist(T);
00674 return TRUE;
00675
00676
00677 } else {
00678 return MAYBE;
00679 }
00680 }