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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "espresso.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050 pcover expand(F, R, nonsparse)
00051 INOUT pcover F;
00052 IN pcover R;
00053 IN bool nonsparse;
00054 {
00055 register pcube last, p;
00056 pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
00057 int var, num_covered;
00058 bool change;
00059
00060
00061 if (use_random_order)
00062 F = random_order(F);
00063 else
00064 F = mini_sort(F, ascend);
00065
00066
00067 RAISE = new_cube();
00068 FREESET = new_cube();
00069 INIT_LOWER = new_cube();
00070 SUPER_CUBE = new_cube();
00071 OVEREXPANDED_CUBE = new_cube();
00072
00073
00074 if (nonsparse)
00075 for(var = 0; var < cube.num_vars; var++)
00076 if (cube.sparse[var])
00077 (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
00078
00079
00080 foreach_set(F, last, p) {
00081 RESET(p, COVERED);
00082 RESET(p, NONESSEN);
00083 }
00084
00085
00086 foreach_set(F, last, p) {
00087
00088 if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
00089
00090
00091 expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
00092 INIT_LOWER, &num_covered, p);
00093 if (debug & EXPAND)
00094 printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
00095 (void) set_copy(p, RAISE);
00096 SET(p, PRIME);
00097 RESET(p, COVERED);
00098
00099
00100 if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
00101 SET(p, NONESSEN);
00102 }
00103 }
00104 }
00105
00106
00107 F->active_count = 0;
00108 change = FALSE;
00109 foreach_set(F, last, p) {
00110 if (TESTP(p, COVERED)) {
00111 RESET(p, ACTIVE);
00112 change = TRUE;
00113 } else {
00114 SET(p, ACTIVE);
00115 F->active_count++;
00116 }
00117 }
00118 if (change)
00119 F = sf_inactive(F);
00120
00121 free_cube(RAISE);
00122 free_cube(FREESET);
00123 free_cube(INIT_LOWER);
00124 free_cube(SUPER_CUBE);
00125 free_cube(OVEREXPANDED_CUBE);
00126 return F;
00127 }
00128
00129
00130
00131
00132 void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
00133 INIT_LOWER, num_covered, c)
00134 pcover BB;
00135 pcover CC;
00136 pcube RAISE;
00137 pcube FREESET;
00138 pcube OVEREXPANDED_CUBE;
00139 pcube SUPER_CUBE;
00140 pcube INIT_LOWER;
00141 int *num_covered;
00142 pcube c;
00143 {
00144 int bestindex;
00145
00146 if (debug & EXPAND1)
00147 printf("\nEXPAND1: \t%s\n", pc1(c));
00148
00149
00150 SET(c, PRIME);
00151 setup_BB_CC(BB, CC);
00152
00153
00154 *num_covered = 0;
00155 (void) set_copy(SUPER_CUBE, c);
00156
00157
00158 (void) set_copy(RAISE, c);
00159 (void) set_diff(FREESET, cube.fullset, RAISE);
00160
00161
00162 if (! setp_empty(INIT_LOWER)) {
00163 (void) set_diff(FREESET, FREESET, INIT_LOWER);
00164 elim_lowering(BB, CC, RAISE, FREESET);
00165 }
00166
00167
00168 essen_parts(BB, CC, RAISE, FREESET);
00169 (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
00170
00171
00172 if (CC->active_count > 0) {
00173 select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
00174 }
00175
00176
00177 while (CC->active_count > 0) {
00178 bestindex = most_frequent(CC, FREESET);
00179 set_insert(RAISE, bestindex);
00180 set_remove(FREESET, bestindex);
00181 essen_parts(BB, CC, RAISE, FREESET);
00182 }
00183
00184
00185
00186 while (BB->active_count > 0) {
00187 mincov(BB, RAISE, FREESET);
00188 }
00189
00190
00191 (void) set_or(RAISE, RAISE, FREESET);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void essen_parts(BB, CC, RAISE, FREESET)
00208 pcover BB, CC;
00209 pcube RAISE, FREESET;
00210 {
00211 register pcube p, r = RAISE;
00212 pcube lastp, xlower = cube.temp[0];
00213 int dist;
00214
00215 (void) set_copy(xlower, cube.emptyset);
00216
00217 foreach_active_set(BB, lastp, p) {
00218 #ifdef NO_INLINE
00219 if ((dist = cdist01(p, r)) > 1) goto exit_if;
00220 #else
00221 {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
00222 {x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
00223 exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
00224 dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
00225 mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
00226 var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
00227 w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
00228 #endif
00229 if (dist == 0) {
00230 fatal("ON-set and OFF-set are not orthogonal");
00231 } else {
00232 (void) force_lower(xlower, p, r);
00233 BB->active_count--;
00234 RESET(p, ACTIVE);
00235 }
00236 exit_if: ;
00237 }
00238
00239 if (! setp_empty(xlower)) {
00240 (void) set_diff(FREESET, FREESET, xlower);
00241 elim_lowering(BB, CC, RAISE, FREESET);
00242 }
00243
00244 if (debug & EXPAND1)
00245 printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 void essen_raising(BB, RAISE, FREESET)
00257 register pcover BB;
00258 pcube RAISE, FREESET;
00259 {
00260 register pcube last, p, xraise = cube.temp[0];
00261
00262
00263 (void) set_copy(xraise, cube.emptyset);
00264 foreach_active_set(BB, last, p)
00265 INLINEset_or(xraise, xraise, p);
00266 (void) set_diff(xraise, FREESET, xraise);
00267
00268 (void) set_or(RAISE, RAISE, xraise);
00269 (void) set_diff(FREESET, FREESET, xraise);
00270
00271 if (debug & EXPAND1)
00272 printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
00273 pc1(RAISE), pc2(FREESET));
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 void elim_lowering(BB, CC, RAISE, FREESET)
00286 pcover BB, CC;
00287 pcube RAISE, FREESET;
00288 {
00289 register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
00290 pcube last;
00291
00292
00293
00294
00295 foreach_active_set(BB, last, p) {
00296 #ifdef NO_INLINE
00297 if (! cdist0(p, r))
00298 #else
00299 {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
00300 lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
00301 &r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
00302 pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
00303 var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
00304 if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
00305 #endif
00306 BB->active_count--, RESET(p, ACTIVE);
00307 }
00308
00309
00310
00311
00312
00313 if (CC != (pcover) NULL) {
00314 foreach_active_set(CC, last, p) {
00315 #ifdef NO_INLINE
00316 if (! setp_implies(p, r))
00317 #else
00318 INLINEsetp_implies(p, r, goto false1);
00319 continue;
00320 false1:
00321 #endif
00322 CC->active_count--, RESET(p, ACTIVE);
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 int most_frequent(CC, FREESET)
00336 pcover CC;
00337 pcube FREESET;
00338 {
00339 register int i, best_part, best_count, *count;
00340 register pset p, last;
00341
00342
00343 count = ALLOC(int, cube.size);
00344 for(i = 0; i < cube.size; i++)
00345 count[i] = 0;
00346 if (CC != (pcover) NULL)
00347 foreach_active_set(CC, last, p)
00348 set_adjcnt(p, count, 1);
00349
00350
00351 best_count = best_part = -1;
00352 for(i = 0; i < cube.size; i++)
00353 if (is_in_set(FREESET,i) && count[i] > best_count) {
00354 best_part = i;
00355 best_count = count[i];
00356 }
00357 FREE(count);
00358
00359 if (debug & EXPAND1)
00360 printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
00361 return best_part;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 void setup_BB_CC(BB, CC)
00373 register pcover BB, CC;
00374 {
00375 register pcube p, last;
00376
00377
00378 BB->active_count = BB->count;
00379 foreach_set(BB, last, p)
00380 SET(p, ACTIVE);
00381
00382 if (CC != (pcover) NULL) {
00383 CC->active_count = CC->count;
00384 foreach_set(CC, last, p)
00385 if (TESTP(p, COVERED) || TESTP(p, PRIME))
00386 CC->active_count--, RESET(p, ACTIVE);
00387 else
00388 SET(p, ACTIVE);
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
00402 pcover BB, CC;
00403 pcube RAISE, FREESET, SUPER_CUBE;
00404 int *num_covered;
00405 {
00406 register pcube p, last, bestfeas, *feas;
00407 register int i, j;
00408 pcube *feas_new_lower;
00409 int bestcount, bestsize, count, size, numfeas, lastfeas;
00410 pcover new_lower;
00411
00412
00413
00414
00415 feas = ALLOC(pcube, CC->active_count);
00416 numfeas = 0;
00417 foreach_active_set(CC, last, p)
00418 feas[numfeas++] = p;
00419
00420
00421 feas_new_lower = ALLOC(pcube, CC->active_count);
00422 new_lower = new_cover(numfeas);
00423 for(i = 0; i < numfeas; i++)
00424 feas_new_lower[i] = GETSET(new_lower, i);
00425
00426
00427 loop:
00428
00429
00430
00431 essen_raising(BB, RAISE, FREESET);
00432
00433
00434 lastfeas = numfeas;
00435 numfeas = 0;
00436 for(i = 0; i < lastfeas; i++) {
00437 p = feas[i];
00438
00439
00440 if (TESTP(p, ACTIVE)) {
00441
00442
00443
00444
00445
00446 if (setp_implies(p, RAISE)) {
00447 (*num_covered) += 1;
00448 (void) set_or(SUPER_CUBE, SUPER_CUBE, p);
00449 CC->active_count--;
00450 RESET(p, ACTIVE);
00451 SET(p, COVERED);
00452
00453 } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
00454 feas[numfeas] = p;
00455 numfeas++;
00456 }
00457 }
00458 }
00459 if (debug & EXPAND1)
00460 printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
00461 lastfeas, numfeas);
00462
00463
00464 if (numfeas == 0) {
00465 FREE(feas);
00466 FREE(feas_new_lower);
00467 free_cover(new_lower);
00468 return;
00469 }
00470
00471
00472 bestcount = 0;
00473 bestsize = 9999;
00474 for(i = 0; i < numfeas; i++) {
00475 size = set_dist(feas[i], FREESET);
00476 count = 0;
00477
00478 #define NEW
00479 #ifdef NEW
00480 for(j = 0; j < numfeas; j++)
00481 if (setp_disjoint(feas_new_lower[i], feas[j]))
00482 count++;
00483 #else
00484 for(j = 0; j < numfeas; j++)
00485 if (setp_implies(feas[j], feas[i]))
00486 count++;
00487 #endif
00488 if (count > bestcount) {
00489 bestcount = count;
00490 bestfeas = feas[i];
00491 bestsize = size;
00492 } else if (count == bestcount && size < bestsize) {
00493 bestfeas = feas[i];
00494 bestsize = size;
00495 }
00496 }
00497
00498
00499 (void) set_or(RAISE, RAISE, bestfeas);
00500 (void) set_diff(FREESET, FREESET, RAISE);
00501 if (debug & EXPAND1)
00502 printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
00503 essen_parts(BB, CC, RAISE, FREESET);
00504 goto loop;
00505
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 bool feasibly_covered(BB, c, RAISE, new_lower)
00517 pcover BB;
00518 pcube c, RAISE, new_lower;
00519 {
00520 register pcube p, r = set_or(cube.temp[0], RAISE, c);
00521 int dist;
00522 pcube lastp;
00523
00524 set_copy(new_lower, cube.emptyset);
00525 foreach_active_set(BB, lastp, p) {
00526 #ifdef NO_INLINE
00527 if ((dist = cdist01(p, r)) > 1) goto exit_if;
00528 #else
00529 {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
00530 {x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
00531 exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
00532 dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
00533 mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
00534 var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
00535 w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
00536 #endif
00537 if (dist == 0)
00538 return FALSE;
00539 else
00540 (void) force_lower(new_lower, p, r);
00541 exit_if: ;
00542 }
00543 return TRUE;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 void mincov(BB, RAISE, FREESET)
00556 pcover BB;
00557 pcube RAISE, FREESET;
00558 {
00559 int expansion, nset, var, dist;
00560 pset_family B;
00561 register pcube xraise=cube.temp[0], xlower, p, last, plower;
00562
00563 #ifdef RANDOM_MINCOV
00564 #if defined(_POSIX_SOURCE) || defined(__SVR4)
00565 dist = rand() % set_ord(FREESET);
00566 #else
00567 dist = random() % set_ord(FREESET);
00568 #endif
00569 for(var = 0; var < cube.size && dist >= 0; var++) {
00570 if (is_in_set(FREESET, var)) {
00571 dist--;
00572 }
00573 }
00574
00575 set_insert(RAISE, var);
00576 set_remove(FREESET, var);
00577 (void) essen_parts(BB, (pcover) NULL, RAISE, FREESET);
00578 #else
00579
00580
00581 B = new_cover(BB->active_count);
00582 foreach_active_set(BB, last, p) {
00583 plower = set_copy(GETSET(B, B->count++), cube.emptyset);
00584 (void) force_lower(plower, p, RAISE);
00585 }
00586
00587
00588 nset = 0;
00589 foreach_set(B, last, p) {
00590 expansion = 1;
00591 for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
00592 if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
00593 expansion *= dist;
00594 if (expansion > 500) goto heuristic_mincov;
00595 }
00596 }
00597 nset += expansion;
00598 if (nset > 500) goto heuristic_mincov;
00599 }
00600
00601 B = unravel(B, cube.num_binary_vars);
00602 xlower = do_sm_minimum_cover(B);
00603
00604
00605 (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
00606 (void) set_copy(FREESET, cube.emptyset);
00607 BB->active_count = 0;
00608 if (debug & EXPAND1) {
00609 printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
00610 }
00611 sf_free(B);
00612 set_free(xlower);
00613 return;
00614
00615 heuristic_mincov:
00616 sf_free(B);
00617
00618 set_insert(RAISE, most_frequent( (pcover) NULL, FREESET));
00619 (void) set_diff(FREESET, FREESET, RAISE);
00620 essen_parts(BB, (pcover) NULL, RAISE, FREESET);
00621 return;
00622 #endif
00623 }
00624
00625
00626
00627
00628
00629 pcover find_all_primes(BB, RAISE, FREESET)
00630 pcover BB;
00631 register pcube RAISE, FREESET;
00632 {
00633 register pset last, p, plower;
00634 pset_family B, B1;
00635
00636 if (BB->active_count == 0) {
00637 B1 = new_cover(1);
00638 p = GETSET(B1, B1->count++);
00639 (void) set_copy(p, RAISE);
00640 SET(p, PRIME);
00641 } else {
00642 B = new_cover(BB->active_count);
00643 foreach_active_set(BB, last, p) {
00644 plower = set_copy(GETSET(B, B->count++), cube.emptyset);
00645 (void) force_lower(plower, p, RAISE);
00646 }
00647 B = sf_rev_contain(unravel(B, cube.num_binary_vars));
00648 B1 = exact_minimum_cover(B);
00649 foreach_set(B1, last, p) {
00650 INLINEset_diff(p, FREESET, p);
00651 INLINEset_or(p, p, RAISE);
00652 SET(p, PRIME);
00653 }
00654 free_cover(B);
00655 }
00656 return B1;
00657 }
00658
00659
00660
00661
00662
00663
00664 pcover all_primes(F, R)
00665 pcover F, R;
00666 {
00667 register pcube last, p, RAISE, FREESET;
00668 pcover Fall_primes, B1;
00669
00670 FREESET = new_cube();
00671 RAISE = new_cube();
00672 Fall_primes = new_cover(F->count);
00673
00674 foreach_set(F, last, p) {
00675 if (TESTP(p, PRIME)) {
00676 Fall_primes = sf_addset(Fall_primes, p);
00677 } else {
00678
00679 (void) set_copy(RAISE, p);
00680 (void) set_diff(FREESET, cube.fullset, RAISE);
00681 setup_BB_CC(R, (pcover) NULL);
00682 essen_parts(R, (pcover) NULL, RAISE, FREESET);
00683
00684
00685 B1 = find_all_primes(R, RAISE, FREESET);
00686 Fall_primes = sf_append(Fall_primes, B1);
00687 }
00688 }
00689
00690 set_free(RAISE);
00691 set_free(FREESET);
00692 return Fall_primes;
00693 }