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 }