00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "espresso.h"
00011
00012 static void fcube_is_covered();
00013 static void ftautology();
00014 static bool ftaut_special_cases();
00015
00016
00017 static int Rp_current;
00018
00019
00020
00021
00022
00023 pcover
00024 irredundant(F, D)
00025 pcover F, D;
00026 {
00027 mark_irredundant(F, D);
00028 return sf_inactive(F);
00029 }
00030
00031
00032
00033
00034
00035
00036 void
00037 mark_irredundant(F, D)
00038 pcover F, D;
00039 {
00040 pcover E, Rt, Rp;
00041 pset p, p1, last;
00042 sm_matrix *table;
00043 sm_row *cover;
00044 sm_element *pe;
00045
00046
00047 irred_split_cover(F, D, &E, &Rt, &Rp);
00048 table = irred_derive_table(D, E, Rp);
00049 cover = sm_minimum_cover(table, NIL(int), 1, 0);
00050
00051
00052 foreach_set(F, last, p) {
00053 RESET(p, ACTIVE);
00054 RESET(p, RELESSEN);
00055 }
00056 foreach_set(E, last, p) {
00057 p1 = GETSET(F, SIZE(p));
00058 assert(setp_equal(p1, p));
00059 SET(p1, ACTIVE);
00060 SET(p1, RELESSEN);
00061 }
00062 sm_foreach_row_element(cover, pe) {
00063 p1 = GETSET(F, pe->col_num);
00064 SET(p1, ACTIVE);
00065 }
00066
00067 if (debug & IRRED) {
00068 printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
00069 F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
00070 cover->length, E->count + cover->length, 0);
00071 }
00072
00073 free_cover(E);
00074 free_cover(Rt);
00075 free_cover(Rp);
00076 sm_free(table);
00077 sm_row_free(cover);
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 void
00089 irred_split_cover(F, D, E, Rt, Rp)
00090 pcover F, D;
00091 pcover *E, *Rt, *Rp;
00092 {
00093 register pcube p, last;
00094 register int index;
00095 pcover R;
00096 pcube *FD, *ED;
00097
00098
00099 index = 0;
00100 foreach_set(F, last, p) {
00101 PUTSIZE(p, index);
00102 index++;
00103 }
00104
00105 *E = new_cover(10);
00106 *Rt = new_cover(10);
00107 *Rp = new_cover(10);
00108 R = new_cover(10);
00109
00110
00111 FD = cube2list(F, D);
00112 foreach_set(F, last, p) {
00113 if (cube_is_covered(FD, p)) {
00114 R = sf_addset(R, p);
00115 } else {
00116 *E = sf_addset(*E, p);
00117 }
00118 if (debug & IRRED1) {
00119 (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
00120 R->count, (*E)->count, F->count - (R->count + (*E)->count),
00121 print_time(ptime()));
00122 }
00123 }
00124 free_cubelist(FD);
00125
00126
00127 ED = cube2list(*E, D);
00128 foreach_set(R, last, p) {
00129 if (cube_is_covered(ED, p)) {
00130 *Rt = sf_addset(*Rt, p);
00131 } else {
00132 *Rp = sf_addset(*Rp, p);
00133 }
00134 if (debug & IRRED1) {
00135 (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
00136 (*Rp)->count, (*Rt)->count,
00137 R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
00138 }
00139 }
00140 free_cubelist(ED);
00141
00142 free_cover(R);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151 sm_matrix *
00152 irred_derive_table(D, E, Rp)
00153 pcover D, E, Rp;
00154 {
00155 register pcube last, p, *list;
00156 sm_matrix *table;
00157 int size_last_dominance, i;
00158
00159
00160 foreach_set(D, last, p) {
00161 RESET(p, REDUND);
00162 }
00163 foreach_set(E, last, p) {
00164 RESET(p, REDUND);
00165 }
00166
00167
00168 foreach_set(Rp, last, p) {
00169 SET(p, REDUND);
00170 }
00171
00172
00173 list = cube3list(D, E, Rp);
00174 table = sm_alloc();
00175 size_last_dominance = 0;
00176 i = 0;
00177 foreach_set(Rp, last, p) {
00178 Rp_current = SIZE(p);
00179 fcube_is_covered(list, p, table);
00180 RESET(p, REDUND);
00181 if (debug & IRRED1) {
00182 (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
00183 i, Rp->count, Rp->count - i,
00184 table->nrows, table->ncols, print_time(ptime()));
00185 }
00186
00187 if (table->nrows - size_last_dominance > 1000) {
00188 (void) sm_row_dominance(table);
00189 size_last_dominance = table->nrows;
00190 if (debug & IRRED1) {
00191 (void) printf("IRRED1: delete redundant rows, now %dx%d\n",
00192 table->nrows, table->ncols);
00193 }
00194 }
00195 i++;
00196 }
00197 free_cubelist(list);
00198
00199 return table;
00200 }
00201
00202
00203 bool
00204 cube_is_covered(T, c)
00205 pcube *T, c;
00206 {
00207 return tautology(cofactor(T,c));
00208 }
00209
00210
00211
00212
00213 bool
00214 tautology(T)
00215 pcube *T;
00216 {
00217 register pcube cl, cr;
00218 register int best, result;
00219 static int taut_level = 0;
00220
00221 if (debug & TAUT) {
00222 debug_print(T, "TAUTOLOGY", taut_level++);
00223 }
00224
00225 if ((result = taut_special_cases(T)) == MAYBE) {
00226 cl = new_cube();
00227 cr = new_cube();
00228 best = binate_split_select(T, cl, cr, TAUT);
00229 result = tautology(scofactor(T, cl, best)) &&
00230 tautology(scofactor(T, cr, best));
00231 free_cubelist(T);
00232 free_cube(cl);
00233 free_cube(cr);
00234 }
00235
00236 if (debug & TAUT) {
00237 printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
00238 }
00239 return result;
00240 }
00241
00242
00243
00244
00245
00246 bool
00247 taut_special_cases(T)
00248 pcube *T;
00249 {
00250 register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
00251 pcube *A, *B;
00252 int var;
00253
00254
00255 for(T1 = T+2; (p = *T1++) != NULL; ) {
00256 if (full_row(p, T[0])) {
00257 free_cubelist(T);
00258 return TRUE;
00259 }
00260 }
00261
00262
00263 start:
00264 INLINEset_copy(ceil, T[0]);
00265 for(T1 = T+2; (p = *T1++) != NULL; ) {
00266 INLINEset_or(ceil, ceil, p);
00267 }
00268 if (! setp_equal(ceil, cube.fullset)) {
00269 free_cubelist(T);
00270 return FALSE;
00271 }
00272
00273
00274 massive_count(T);
00275
00276
00277 if (cdata.vars_unate == cdata.vars_active) {
00278 free_cubelist(T);
00279 return FALSE;
00280
00281
00282 } else if (cdata.vars_active == 1) {
00283 free_cubelist(T);
00284 return TRUE;
00285
00286
00287 } else if (cdata.vars_unate != 0) {
00288
00289 (void) set_copy(ceil, cube.emptyset);
00290 for(var = 0; var < cube.num_vars; var++) {
00291 if (cdata.is_unate[var]) {
00292 INLINEset_or(ceil, ceil, cube.var_mask[var]);
00293 }
00294 }
00295
00296
00297 for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
00298 if (setp_implies(ceil, set_or(temp, p, T[0]))) {
00299 *Tsave++ = p;
00300 }
00301 }
00302 *Tsave++ = NULL;
00303 T[1] = (pcube) Tsave;
00304
00305 if (debug & TAUT) {
00306 printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
00307 cdata.vars_unate, CUBELISTSIZE(T));
00308 }
00309 goto start;
00310
00311
00312 } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
00313 if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
00314 return MAYBE;
00315 } else {
00316 free_cubelist(T);
00317 if (tautology(A)) {
00318 free_cubelist(B);
00319 return TRUE;
00320 } else {
00321 return tautology(B);
00322 }
00323 }
00324 }
00325
00326
00327 return MAYBE;
00328 }
00329
00330
00331 static void
00332 fcube_is_covered(T, c, table)
00333 pcube *T, c;
00334 sm_matrix *table;
00335 {
00336 ftautology(cofactor(T,c), table);
00337 }
00338
00339
00340
00341 static void
00342 ftautology(T, table)
00343 pcube *T;
00344 sm_matrix *table;
00345 {
00346 register pcube cl, cr;
00347 register int best;
00348 static int ftaut_level = 0;
00349
00350 if (debug & TAUT) {
00351 debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
00352 }
00353
00354 if (ftaut_special_cases(T, table) == MAYBE) {
00355 cl = new_cube();
00356 cr = new_cube();
00357 best = binate_split_select(T, cl, cr, TAUT);
00358
00359 ftautology(scofactor(T, cl, best), table);
00360 ftautology(scofactor(T, cr, best), table);
00361
00362 free_cubelist(T);
00363 free_cube(cl);
00364 free_cube(cr);
00365 }
00366
00367 if (debug & TAUT) {
00368 (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
00369 --ftaut_level, table->nrows, table->ncols);
00370 }
00371 }
00372
00373 static bool
00374 ftaut_special_cases(T, table)
00375 pcube *T;
00376 sm_matrix *table;
00377 {
00378 register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
00379 int var, rownum;
00380
00381
00382 for(T1 = T+2; (p = *T1++) != 0; ) {
00383 if (! TESTP(p, REDUND)) {
00384 if (full_row(p, T[0])) {
00385
00386 free_cubelist(T);
00387 return TRUE;
00388 }
00389 }
00390 }
00391
00392
00393 start:
00394 massive_count(T);
00395
00396
00397 if (cdata.vars_unate == cdata.vars_active) {
00398
00399 rownum = table->last_row ? table->last_row->row_num+1 : 0;
00400 (void) sm_insert(table, rownum, Rp_current);
00401 for(T1 = T+2; (p = *T1++) != 0; ) {
00402 if (TESTP(p, REDUND)) {
00403
00404 if (full_row(p, T[0])) {
00405 (void) sm_insert(table, rownum, (int) SIZE(p));
00406 }
00407 }
00408 }
00409 free_cubelist(T);
00410 return TRUE;
00411
00412
00413 } else if (cdata.vars_unate != 0) {
00414
00415 (void) set_copy(ceil, cube.emptyset);
00416 for(var = 0; var < cube.num_vars; var++) {
00417 if (cdata.is_unate[var]) {
00418 INLINEset_or(ceil, ceil, cube.var_mask[var]);
00419 }
00420 }
00421
00422
00423 for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
00424 if (setp_implies(ceil, set_or(temp, p, T[0]))) {
00425 *Tsave++ = p;
00426 }
00427 }
00428 *Tsave++ = 0;
00429 T[1] = (pcube) Tsave;
00430
00431 if (debug & TAUT) {
00432 printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
00433 cdata.vars_unate, CUBELISTSIZE(T));
00434 }
00435 goto start;
00436 }
00437
00438
00439 return MAYBE;
00440 }