00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "espresso.h"
00017 #include "main.h"
00018
00019 static FILE *last_fp;
00020 static int input_type = FD_type;
00021
00022
00023 main(argc, argv)
00024 int argc;
00025 char *argv[];
00026 {
00027 int i, j, first, last, strategy, out_type, option;
00028 pPLA PLA, PLA1;
00029 pcover F, Fold, Dold;
00030 pset last1, p;
00031 cost_t cost;
00032 bool error, exact_cover;
00033 long start;
00034 extern char *util_optarg;
00035 extern int util_optind;
00036
00037 start = ptime();
00038
00039 error = FALSE;
00040 init_runtime();
00041 #ifdef RANDOM
00042 srandom(314973);
00043 #endif
00044
00045 option = 0;
00046 out_type = F_type;
00047 debug = 0;
00048 verbose_debug = FALSE;
00049 print_solution = TRUE;
00050 summary = FALSE;
00051 trace = FALSE;
00052 strategy = 0;
00053 first = -1;
00054 last = -1;
00055 remove_essential = TRUE;
00056 force_irredundant = TRUE;
00057 unwrap_onset = TRUE;
00058 single_expand = FALSE;
00059 pos = FALSE;
00060 recompute_onset = FALSE;
00061 use_super_gasp = FALSE;
00062 use_random_order = FALSE;
00063 kiss = FALSE;
00064 echo_comments = TRUE;
00065 echo_unknown_commands = TRUE;
00066 exact_cover = FALSE;
00067
00068 backward_compatibility_hack(&argc, argv, &option, &out_type);
00069
00070
00071
00072 while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
00073 switch(i) {
00074 case 'D':
00075 for(j = 0; option_table[j].name != 0; j++) {
00076 if (strcmp(util_optarg, option_table[j].name) == 0) {
00077 option = j;
00078 break;
00079 }
00080 }
00081 if (option_table[j].name == 0) {
00082 (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n",
00083 argv[0], util_optarg);
00084 exit(1);
00085 }
00086 break;
00087
00088 case 'o':
00089 for(j = 0; pla_types[j].key != 0; j++) {
00090 if (strcmp(util_optarg, pla_types[j].key+1) == 0) {
00091 out_type = pla_types[j].value;
00092 break;
00093 }
00094 }
00095 if (pla_types[j].key == 0) {
00096 (void) fprintf(stderr, "%s: bad output type \"%s\"\n",
00097 argv[0], util_optarg);
00098 exit(1);
00099 }
00100 break;
00101
00102 case 'e':
00103 for(j = 0; esp_opt_table[j].name != 0; j++) {
00104 if (strcmp(util_optarg, esp_opt_table[j].name) == 0) {
00105 *(esp_opt_table[j].variable) = esp_opt_table[j].value;
00106 break;
00107 }
00108 }
00109 if (esp_opt_table[j].name == 0) {
00110 (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n",
00111 argv[0], util_optarg);
00112 exit(1);
00113 }
00114 break;
00115
00116 case 'd':
00117 debug = debug_table[0].value;
00118 trace = TRUE;
00119 summary = TRUE;
00120 break;
00121
00122 case 'v':
00123 verbose_debug = TRUE;
00124 for(j = 0; debug_table[j].name != 0; j++) {
00125 if (strcmp(util_optarg, debug_table[j].name) == 0) {
00126 debug |= debug_table[j].value;
00127 break;
00128 }
00129 }
00130 if (debug_table[j].name == 0) {
00131 (void) fprintf(stderr, "%s: bad debug type \"%s\"\n",
00132 argv[0], util_optarg);
00133 exit(1);
00134 }
00135 break;
00136
00137 case 't':
00138 trace = TRUE;
00139 break;
00140
00141 case 's':
00142 summary = TRUE;
00143 break;
00144
00145 case 'x':
00146 print_solution = FALSE;
00147 break;
00148
00149 case 'S':
00150 strategy = atoi(util_optarg);
00151 break;
00152
00153 case 'r':
00154 if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) {
00155 (void) fprintf(stderr, "%s: bad output range \"%s\"\n",
00156 argv[0], util_optarg);
00157 exit(1);
00158 }
00159 break;
00160
00161 default:
00162 usage();
00163 exit(1);
00164 }
00165 }
00166
00167
00168 if (summary || trace) {
00169
00170 printf("#");
00171 for(i = 0; i < argc; i++) {
00172 printf(" %s", argv[i]);
00173 }
00174 printf("\n");
00175 printf("# %s\n", VERSION);
00176 }
00177
00178
00179 PLA = PLA1 = NIL(PLA_t);
00180 switch(option_table[option].num_plas) {
00181 case 2:
00182 if (util_optind+2 < argc) fatal("trailing arguments on command line");
00183 getPLA(util_optind++, argc, argv, option, &PLA, out_type);
00184 getPLA(util_optind++, argc, argv, option, &PLA1, out_type);
00185 break;
00186 case 1:
00187 if (util_optind+1 < argc) fatal("trailing arguments on command line");
00188 getPLA(util_optind++, argc, argv, option, &PLA, out_type);
00189 break;
00190 }
00191 if (util_optind < argc) fatal("trailing arguments on command line");
00192
00193 if (summary || trace) {
00194 if (PLA != NIL(PLA_t)) PLA_summary(PLA);
00195 if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
00196 }
00197
00198
00199
00200
00201
00202 switch(option_table[option].key) {
00203
00204
00205
00206
00207 case KEY_ESPRESSO:
00208 Fold = sf_save(PLA->F);
00209 PLA->F = espresso(PLA->F, PLA->D, PLA->R);
00210 EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
00211 if (error) {
00212 print_solution = FALSE;
00213 PLA->F = Fold;
00214 (void) check_consistency(PLA);
00215 } else {
00216 free_cover(Fold);
00217 }
00218 break;
00219
00220 case KEY_MANY_ESPRESSO: {
00221 int pla_type;
00222 do {
00223 EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
00224 if (print_solution) {
00225 fprint_pla(stdout, PLA, out_type);
00226 (void) fflush(stdout);
00227 }
00228 pla_type = PLA->pla_type;
00229 free_PLA(PLA);
00230 setdown_cube();
00231 FREE(cube.part_size);
00232 } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
00233 exit(0);
00234 }
00235
00236 case KEY_simplify:
00237 EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F);
00238 break;
00239
00240 case KEY_so:
00241 if (strategy < 0 || strategy > 1) {
00242 strategy = 0;
00243 }
00244 so_espresso(PLA, strategy);
00245 break;
00246
00247 case KEY_so_both:
00248 if (strategy < 0 || strategy > 1) {
00249 strategy = 0;
00250 }
00251 so_both_espresso(PLA, strategy);
00252 break;
00253
00254 case KEY_expand:
00255 EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
00256 break;
00257
00258 case KEY_irred:
00259 EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
00260 break;
00261
00262 case KEY_reduce:
00263 EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
00264 break;
00265
00266 case KEY_essen:
00267 foreach_set(PLA->F, last1, p) {
00268 SET(p, RELESSEN);
00269 RESET(p, NONESSEN);
00270 }
00271 EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
00272 free_cover(F);
00273 break;
00274
00275 case KEY_super_gasp:
00276 PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
00277 break;
00278
00279 case KEY_gasp:
00280 PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
00281 break;
00282
00283 case KEY_make_sparse:
00284 PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
00285 break;
00286
00287 case KEY_exact:
00288 exact_cover = TRUE;
00289
00290 case KEY_qm:
00291 Fold = sf_save(PLA->F);
00292 PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
00293 EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
00294 if (error) {
00295 print_solution = FALSE;
00296 PLA->F = Fold;
00297 (void) check_consistency(PLA);
00298 }
00299 free_cover(Fold);
00300 break;
00301
00302 case KEY_primes:
00303 EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)),
00304 "PRIMES ", PLA->F);
00305 break;
00306
00307 case KEY_map:
00308 map(PLA->F);
00309 print_solution = FALSE;
00310 break;
00311
00312
00313
00314
00315
00316 case KEY_opo:
00317 phase_assignment(PLA, strategy);
00318 break;
00319
00320 case KEY_opoall:
00321 if (first < 0 || first >= cube.part_size[cube.output]) {
00322 first = 0;
00323 }
00324 if (last < 0 || last >= cube.part_size[cube.output]) {
00325 last = cube.part_size[cube.output] - 1;
00326 }
00327 opoall(PLA, first, last, strategy);
00328 break;
00329
00330 case KEY_pair:
00331 find_optimal_pairing(PLA, strategy);
00332 break;
00333
00334 case KEY_pairall:
00335 pair_all(PLA, strategy);
00336 break;
00337
00338
00339
00340
00341
00342 case KEY_echo:
00343 break;
00344
00345 case KEY_taut:
00346 printf("ON-set is%sa tautology\n",
00347 tautology(cube1list(PLA->F)) ? " " : " not ");
00348 print_solution = FALSE;
00349 break;
00350
00351 case KEY_contain:
00352 PLA->F = sf_contain(PLA->F);
00353 break;
00354
00355 case KEY_intersect:
00356 PLA->F = cv_intersect(PLA->F, PLA1->F);
00357 break;
00358
00359 case KEY_union:
00360 PLA->F = sf_union(PLA->F, PLA1->F);
00361 break;
00362
00363 case KEY_disjoint:
00364 PLA->F = make_disjoint(PLA->F);
00365 break;
00366
00367 case KEY_dsharp:
00368 PLA->F = cv_dsharp(PLA->F, PLA1->F);
00369 break;
00370
00371 case KEY_sharp:
00372 PLA->F = cv_sharp(PLA->F, PLA1->F);
00373 break;
00374
00375 case KEY_lexsort:
00376 PLA->F = lex_sort(PLA->F);
00377 break;
00378
00379 case KEY_stats:
00380 if (! summary) PLA_summary(PLA);
00381 print_solution = FALSE;
00382 break;
00383
00384 case KEY_minterms:
00385 if (first < 0 || first >= cube.num_vars) {
00386 first = 0;
00387 }
00388 if (last < 0 || last >= cube.num_vars) {
00389 last = cube.num_vars - 1;
00390 }
00391 PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
00392 break;
00393
00394 case KEY_d1merge:
00395 if (first < 0 || first >= cube.num_vars) {
00396 first = 0;
00397 }
00398 if (last < 0 || last >= cube.num_vars) {
00399 last = cube.num_vars - 1;
00400 }
00401 for(i = first; i <= last; i++) {
00402 PLA->F = d1merge(PLA->F, i);
00403 }
00404 break;
00405
00406 case KEY_d1merge_in:
00407 for(i = 0; i < cube.num_binary_vars; i++) {
00408 PLA->F = d1merge(PLA->F, i);
00409 }
00410 break;
00411
00412 case KEY_PLA_verify:
00413 EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
00414 if (error) {
00415 printf("PLA comparison failed; the PLA's are not equivalent\n");
00416 exit(1);
00417 } else {
00418 printf("PLA's compared equal\n");
00419 exit(0);
00420 }
00421 break;
00422
00423 case KEY_verify:
00424 Fold = PLA->F; Dold = PLA->D; F = PLA1->F;
00425 EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
00426 if (error) {
00427 printf("PLA comparison failed; the PLA's are not equivalent\n");
00428 exit(1);
00429 } else {
00430 printf("PLA's compared equal\n");
00431 exit(0);
00432 }
00433 break;
00434
00435 case KEY_check:
00436 (void) check_consistency(PLA);
00437 print_solution = FALSE;
00438 break;
00439
00440 case KEY_mapdc:
00441 map_dcset(PLA);
00442 out_type = FD_type;
00443 break;
00444
00445 case KEY_equiv:
00446 find_equiv_outputs(PLA);
00447 print_solution = FALSE;
00448 break;
00449
00450 case KEY_separate:
00451 PLA->F = complement(cube2list(PLA->D, PLA->R));
00452 break;
00453
00454 case KEY_xor: {
00455 pcover T1 = cv_intersect(PLA->F, PLA1->R);
00456 pcover T2 = cv_intersect(PLA1->F, PLA->R);
00457 free_cover(PLA->F);
00458 PLA->F = sf_contain(sf_join(T1, T2));
00459 free_cover(T1);
00460 free_cover(T2);
00461 break;
00462 }
00463
00464 case KEY_fsm: {
00465 disassemble_fsm(PLA, summary);
00466 print_solution = FALSE;
00467 break;
00468 }
00469
00470 case KEY_test: {
00471 pcover T, E;
00472 T = sf_join(PLA->D, PLA->R);
00473 E = new_cover(10);
00474 sf_free(PLA->F);
00475 EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
00476 EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
00477 EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
00478 sf_free(T);
00479 T = sf_join(PLA->F, PLA->R);
00480 EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
00481 EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
00482 sf_free(T);
00483 sf_free(E);
00484 break;
00485 }
00486
00487
00488 }
00489
00490
00491 if (trace) {
00492 runtime();
00493 }
00494
00495
00496 if (summary || trace) {
00497 print_trace(PLA->F, option_table[option].name, ptime()-start);
00498 }
00499
00500
00501 if (print_solution) {
00502 EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
00503 }
00504
00505
00506 if (error) {
00507 fatal("cover verification failed");
00508 }
00509
00510
00511 free_PLA(PLA);
00512 FREE(cube.part_size);
00513 setdown_cube();
00514 sf_cleanup();
00515 sm_cleanup();
00516
00517 exit(0);
00518 }
00519
00520
00521 getPLA(opt, argc, argv, option, PLA, out_type)
00522 int opt;
00523 int argc;
00524 char *argv[];
00525 int option;
00526 pPLA *PLA;
00527 int out_type;
00528 {
00529 FILE *fp;
00530 int needs_dcset, needs_offset;
00531 char *fname;
00532
00533 if (opt >= argc) {
00534 fp = stdin;
00535 fname = "(stdin)";
00536 } else {
00537 fname = argv[opt];
00538 if (strcmp(fname, "-") == 0) {
00539 fp = stdin;
00540 } else if ((fp = fopen(argv[opt], "r")) == NULL) {
00541 (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
00542 exit(1);
00543 }
00544 }
00545 if (option_table[option].key == KEY_echo) {
00546 needs_dcset = (out_type & D_type) != 0;
00547 needs_offset = (out_type & R_type) != 0;
00548 } else {
00549 needs_dcset = option_table[option].needs_dcset;
00550 needs_offset = option_table[option].needs_offset;
00551 }
00552
00553 if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
00554 (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
00555 exit(1);
00556 }
00557 (*PLA)->filename = util_strsav(fname);
00558 filename = (*PLA)->filename;
00559
00560
00561 last_fp = fp;
00562 }
00563
00564
00565 runtime()
00566 {
00567 int i;
00568 long total = 1, temp;
00569
00570 for(i = 0; i < TIME_COUNT; i++) {
00571 total += total_time[i];
00572 }
00573 for(i = 0; i < TIME_COUNT; i++) {
00574 if (total_calls[i] != 0) {
00575 temp = 100 * total_time[i];
00576 printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
00577 total_name[i], total_calls[i], print_time(total_time[i]),
00578 temp/total, (10 * (temp%total)) / total);
00579 }
00580 }
00581 }
00582
00583
00584 init_runtime()
00585 {
00586 total_name[READ_TIME] = "READ ";
00587 total_name[WRITE_TIME] = "WRITE ";
00588 total_name[COMPL_TIME] = "COMPL ";
00589 total_name[REDUCE_TIME] = "REDUCE ";
00590 total_name[EXPAND_TIME] = "EXPAND ";
00591 total_name[ESSEN_TIME] = "ESSEN ";
00592 total_name[IRRED_TIME] = "IRRED ";
00593 total_name[GREDUCE_TIME] = "REDUCE_GASP";
00594 total_name[GEXPAND_TIME] = "EXPAND_GASP";
00595 total_name[GIRRED_TIME] = "IRRED_GASP ";
00596 total_name[MV_REDUCE_TIME] ="MV_REDUCE ";
00597 total_name[RAISE_IN_TIME] = "RAISE_IN ";
00598 total_name[VERIFY_TIME] = "VERIFY ";
00599 total_name[PRIMES_TIME] = "PRIMES ";
00600 total_name[MINCOV_TIME] = "MINCOV ";
00601 }
00602
00603
00604 subcommands()
00605 {
00606 int i, col;
00607 printf(" ");
00608 col = 16;
00609 for(i = 0; option_table[i].name != 0; i++) {
00610 if ((col + strlen(option_table[i].name) + 1) > 76) {
00611 printf(",\n ");
00612 col = 16;
00613 } else if (i != 0) {
00614 printf(", ");
00615 }
00616 printf("%s", option_table[i].name);
00617 col += strlen(option_table[i].name) + 2;
00618 }
00619 printf("\n");
00620 }
00621
00622
00623 usage()
00624 {
00625 printf("%s\n\n", VERSION);
00626 printf("SYNOPSIS: espresso [options] [file]\n\n");
00627 printf(" -d Enable debugging\n");
00628 printf(" -e[opt] Select espresso option:\n");
00629 printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n");
00630 printf(" eat, eatdots, kiss, random\n");
00631 printf(" -o[type] Select output format:\n");
00632 printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
00633 printf(" -rn-m Select range for subcommands:\n");
00634 printf(" d1merge: first and last variables (0 ... m-1)\n");
00635 printf(" minterms: first and last variables (0 ... m-1)\n");
00636 printf(" opoall: first and last outputs (0 ... m-1)\n");
00637 printf(" -s Provide short execution summary\n");
00638 printf(" -t Provide longer execution trace\n");
00639 printf(" -x Suppress printing of solution\n");
00640 printf(" -v[type] Verbose debugging detail (-v '' for all)\n");
00641 printf(" -D[cmd] Execute subcommand 'cmd':\n");
00642 subcommands();
00643 printf(" -Sn Select strategy for subcommands:\n");
00644 printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n");
00645 printf(" opoall: 0=minimize, 1=exact\n");
00646 printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
00647 printf(" pairall: 0=minimize, 1=exact, 2=opo\n");
00648 printf(" so_espresso: 0=minimize, 1=exact\n");
00649 printf(" so_both: 0=minimize, 1=exact\n");
00650 }
00651
00652
00653
00654
00655
00656 backward_compatibility_hack(argc, argv, option, out_type)
00657 int *argc;
00658 char **argv;
00659 int *option;
00660 int *out_type;
00661 {
00662 int i, j;
00663
00664
00665 *option = 0;
00666 for(i = 1; i < (*argc)-1; i++) {
00667 if (strcmp(argv[i], "-do") == 0) {
00668 for(j = 0; option_table[j].name != 0; j++)
00669 if (strcmp(argv[i+1], option_table[j].name) == 0) {
00670 *option = j;
00671 delete_arg(argc, argv, i+1);
00672 delete_arg(argc, argv, i);
00673 break;
00674 }
00675 if (option_table[j].name == 0) {
00676 (void) fprintf(stderr,
00677 "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
00678 exit(1);
00679 }
00680 break;
00681 }
00682 }
00683
00684 for(i = 1; i < (*argc)-1; i++) {
00685 if (strcmp(argv[i], "-out") == 0) {
00686 for(j = 0; pla_types[j].key != 0; j++)
00687 if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
00688 *out_type = pla_types[j].value;
00689 delete_arg(argc, argv, i+1);
00690 delete_arg(argc, argv, i);
00691 break;
00692 }
00693 if (pla_types[j].key == 0) {
00694 (void) fprintf(stderr,
00695 "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
00696 exit(1);
00697 }
00698 break;
00699 }
00700 }
00701
00702 for(i = 1; i < (*argc); i++) {
00703 if (argv[i][0] == '-') {
00704 for(j = 0; esp_opt_table[j].name != 0; j++) {
00705 if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
00706 delete_arg(argc, argv, i);
00707 *(esp_opt_table[j].variable) = esp_opt_table[j].value;
00708 break;
00709 }
00710 }
00711 }
00712 }
00713
00714 if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
00715 if (check_arg(argc, argv, "-fr")) input_type = FR_type;
00716 if (check_arg(argc, argv, "-f")) input_type = F_type;
00717 }
00718
00719
00720
00721 delete_arg(argc, argv, num)
00722 int *argc, num;
00723 register char *argv[];
00724 {
00725 register int i;
00726 (*argc)--;
00727 for(i = num; i < *argc; i++) {
00728 argv[i] = argv[i+1];
00729 }
00730 }
00731
00732
00733
00734 bool check_arg(argc, argv, s)
00735 int *argc;
00736 register char *argv[], *s;
00737 {
00738 register int i;
00739 for(i = 1; i < *argc; i++) {
00740 if (strcmp(argv[i], s) == 0) {
00741 delete_arg(argc, argv, i);
00742 return TRUE;
00743 }
00744 }
00745 return FALSE;
00746 }