00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "espresso.h"
00011
00012 void set_pair(PLA)
00013 pPLA PLA;
00014 {
00015 set_pair1(PLA, TRUE);
00016 }
00017
00018 void set_pair1(PLA, adjust_labels)
00019 pPLA PLA;
00020 bool adjust_labels;
00021 {
00022 int i, var, *paired, newvar;
00023 int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
00024 int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
00025 ppair pair = PLA->pair;
00026 char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
00027
00028 if (adjust_labels)
00029 makeup_labels(PLA);
00030
00031
00032
00033
00034 paired = ALLOC(bool, cube.num_binary_vars);
00035 for(var = 0; var < cube.num_binary_vars; var++)
00036 paired[var] = FALSE;
00037 for(i = 0; i < pair->cnt; i++)
00038 if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
00039 (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
00040 paired[pair->var1[i]-1] = TRUE;
00041 paired[pair->var2[i]-1] = TRUE;
00042 } else
00043 fatal("can only pair binary-valued variables");
00044
00045 PLA->F = delvar(pairvar(PLA->F, pair), paired);
00046 PLA->R = delvar(pairvar(PLA->R, pair), paired);
00047 PLA->D = delvar(pairvar(PLA->D, pair), paired);
00048
00049
00050 old_size = cube.size;
00051 old_num_vars = cube.num_vars;
00052 old_num_binary_vars = cube.num_binary_vars;
00053 old_mv_start = cube.first_part[cube.num_binary_vars];
00054
00055 new_num_binary_vars = 0;
00056 for(var = 0; var < old_num_binary_vars; var++)
00057 new_num_binary_vars += (paired[var] == FALSE);
00058 new_num_vars = new_num_binary_vars + pair->cnt;
00059 new_num_vars += old_num_vars - old_num_binary_vars;
00060 new_part_size = ALLOC(int, new_num_vars);
00061 for(var = 0; var < pair->cnt; var++)
00062 new_part_size[new_num_binary_vars + var] = 4;
00063 for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
00064 new_part_size[new_num_binary_vars + pair->cnt + var] =
00065 cube.part_size[old_num_binary_vars + var];
00066 setdown_cube();
00067 FREE(cube.part_size);
00068 cube.num_vars = new_num_vars;
00069 cube.num_binary_vars = new_num_binary_vars;
00070 cube.part_size = new_part_size;
00071 cube_setup();
00072
00073
00074 if (adjust_labels) {
00075 oldlabel = PLA->label;
00076 PLA->label = ALLOC(char *, cube.size);
00077 for(var = 0; var < pair->cnt; var++) {
00078 newvar = cube.num_binary_vars*2 + var*4;
00079 var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
00080 var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
00081 var1bar = oldlabel[ (pair->var1[var]-1) * 2];
00082 var2bar = oldlabel[ (pair->var2[var]-1) * 2];
00083 (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
00084 PLA->label[newvar] = util_strsav(scratch);
00085 (void) sprintf(scratch, "%s+%s", var1bar, var2);
00086 PLA->label[newvar+1] = util_strsav(scratch);
00087 (void) sprintf(scratch, "%s+%s", var1, var2bar);
00088 PLA->label[newvar+2] = util_strsav(scratch);
00089 (void) sprintf(scratch, "%s+%s", var1, var2);
00090 PLA->label[newvar+3] = util_strsav(scratch);
00091 }
00092
00093 i = 0;
00094 for(var = 0; var < old_num_binary_vars; var++) {
00095 if (paired[var] == FALSE) {
00096 PLA->label[2*i] = oldlabel[2*var];
00097 PLA->label[2*i+1] = oldlabel[2*var+1];
00098 oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
00099 i++;
00100 }
00101 }
00102
00103 new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
00104 for(i = old_mv_start; i < old_size; i++) {
00105 PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
00106 oldlabel[i] = (char *) NULL;
00107 }
00108
00109 for(i = 0; i < old_size; i++)
00110 if (oldlabel[i] != (char *) NULL)
00111 FREE(oldlabel[i]);
00112 FREE(oldlabel);
00113 }
00114
00115
00116 for(var = 0; var < pair->cnt; var++)
00117 cube.sparse[cube.num_binary_vars + var] = 0;
00118 FREE(paired);
00119 }
00120
00121 pcover pairvar(A, pair)
00122 pcover A;
00123 ppair pair;
00124 {
00125 register pcube last, p;
00126 register int val, p1, p2, b1, b0;
00127 int insert_col, pairnum;
00128
00129 insert_col = cube.first_part[cube.num_vars - 1];
00130
00131
00132 A = sf_delcol(A, insert_col, -4*pair->cnt);
00133
00134
00135 foreach_set(A, last, p) {
00136 for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
00137 p1 = cube.first_part[pair->var1[pairnum] - 1];
00138 p2 = cube.first_part[pair->var2[pairnum] - 1];
00139 b1 = is_in_set(p, p2+1);
00140 b0 = is_in_set(p, p2);
00141 val = insert_col + pairnum * 4;
00142 if ( is_in_set(p, p1)) {
00143 if (b0)
00144 set_insert(p, val + 3);
00145 if (b1)
00146 set_insert(p, val + 2);
00147 }
00148 if ( is_in_set(p, p1+1)) {
00149 if (b0)
00150 set_insert(p, val + 1);
00151 if (b1)
00152 set_insert(p, val);
00153 }
00154 }
00155 }
00156 return A;
00157 }
00158
00159
00160
00161 pcover delvar(A, paired)
00162 pcover A;
00163 bool paired[];
00164 {
00165 bool run;
00166 int first_run, run_length, var, offset = 0;
00167
00168 run = FALSE; run_length = 0;
00169 for(var = 0; var < cube.num_binary_vars; var++)
00170 if (paired[var])
00171 if (run)
00172 run_length += cube.part_size[var];
00173 else {
00174 run = TRUE;
00175 first_run = cube.first_part[var];
00176 run_length = cube.part_size[var];
00177 }
00178 else
00179 if (run) {
00180 A = sf_delcol(A, first_run-offset, run_length);
00181 run = FALSE;
00182 offset += run_length;
00183 }
00184 if (run)
00185 A = sf_delcol(A, first_run-offset, run_length);
00186 return A;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void find_optimal_pairing(PLA, strategy)
00223 pPLA PLA;
00224 int strategy;
00225 {
00226 int i, j, **cost_array;
00227
00228 cost_array = find_pairing_cost(PLA, strategy);
00229
00230 if (summary) {
00231 printf(" ");
00232 for(i = 0; i < cube.num_binary_vars; i++)
00233 printf("%3d ", i+1);
00234 printf("\n");
00235 for(i = 0; i < cube.num_binary_vars; i++) {
00236 printf("%3d ", i+1);
00237 for(j = 0; j < cube.num_binary_vars; j++)
00238 printf("%3d ", cost_array[i][j]);
00239 printf("\n");
00240 }
00241 }
00242
00243 if (cube.num_binary_vars <= 14) {
00244 PLA->pair = pair_best_cost(cost_array);
00245 } else {
00246 (void) greedy_best_cost(cost_array, &(PLA->pair));
00247 }
00248 printf("# ");
00249 print_pair(PLA->pair);
00250
00251 for(i = 0; i < cube.num_binary_vars; i++)
00252 FREE(cost_array[i]);
00253 FREE(cost_array);
00254
00255 set_pair(PLA);
00256 EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
00257 }
00258
00259 int **find_pairing_cost(PLA, strategy)
00260 pPLA PLA;
00261 int strategy;
00262 {
00263 int var1, var2, **cost_array;
00264 int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost;
00265 pcover T, Fsave, Dsave, Rsave;
00266 pset mask;
00267
00268
00269
00270 cost_array = ALLOC(int *, cube.num_binary_vars);
00271 for(i = 0; i < cube.num_binary_vars; i++)
00272 cost_array[i] = ALLOC(int, cube.num_binary_vars);
00273 for(i = 0; i < cube.num_binary_vars; i++)
00274 for(j = 0; j < cube.num_binary_vars; j++)
00275 cost_array[i][j] = 0;
00276
00277
00278 PLA->pair = pair_new(1);
00279 PLA->pair->cnt = 1;
00280
00281 for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
00282 for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
00283
00284 if (strategy > 0) {
00285
00286 Fsave = sf_save(PLA->F);
00287 Dsave = sf_save(PLA->D);
00288 Rsave = sf_save(PLA->R);
00289
00290
00291 xnum_binary_vars = cube.num_binary_vars;
00292 xnum_vars = cube.num_vars;
00293 xpart_size = ALLOC(int, cube.num_vars);
00294 for(i = 0; i < cube.num_vars; i++)
00295 xpart_size[i] = cube.part_size[i];
00296
00297
00298 PLA->pair->var1[0] = var1 + 1;
00299 PLA->pair->var2[0] = var2 + 1;
00300 set_pair1(PLA, FALSE);
00301 }
00302
00303
00304
00305 switch(strategy) {
00306 case 3:
00307
00308 PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
00309 cost = Fsave->count - PLA->F->count;
00310 break;
00311 case 2:
00312
00313 PLA->F = espresso(PLA->F, PLA->D, PLA->R);
00314 cost = Fsave->count - PLA->F->count;
00315 break;
00316 case 1:
00317
00318 PLA->F = reduce(PLA->F, PLA->D);
00319 PLA->F = expand(PLA->F, PLA->R, FALSE);
00320 PLA->F = irredundant(PLA->F, PLA->D);
00321 cost = Fsave->count - PLA->F->count;
00322 break;
00323 case 0:
00324
00325 mask = new_cube();
00326 set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
00327 T = dist_merge(sf_save(PLA->F), mask);
00328 cost = PLA->F->count - T->count;
00329 sf_free(T);
00330 set_free(mask);
00331 }
00332
00333 cost_array[var1][var2] = cost;
00334
00335 if (strategy > 0) {
00336
00337 setdown_cube();
00338 FREE(cube.part_size);
00339 cube.num_binary_vars = xnum_binary_vars;
00340 cube.num_vars = xnum_vars;
00341 cube.part_size = xpart_size;
00342 cube_setup();
00343
00344
00345 sf_free(PLA->F);
00346 sf_free(PLA->D);
00347 sf_free(PLA->R);
00348 PLA->F = Fsave;
00349 PLA->D = Dsave;
00350 PLA->R = Rsave;
00351 }
00352 }
00353 }
00354
00355 pair_free(PLA->pair);
00356 PLA->pair = NULL;
00357 return cost_array;
00358 }
00359
00360 static int best_cost;
00361 static int **cost_array;
00362 static ppair best_pair;
00363 static pset best_phase;
00364 static pPLA global_PLA;
00365 static pcover best_F, best_D, best_R;
00366 static int pair_minim_strategy;
00367
00368
00369 print_pair(pair)
00370 ppair pair;
00371 {
00372 int i;
00373
00374 printf("pair is");
00375 for(i = 0; i < pair->cnt; i++)
00376 printf (" (%d %d)", pair->var1[i], pair->var2[i]);
00377 printf("\n");
00378 }
00379
00380
00381 int greedy_best_cost(cost_array_local, pair_p)
00382 int **cost_array_local;
00383 ppair *pair_p;
00384 {
00385 int i, j, besti, bestj, maxcost, total_cost;
00386 pset cand;
00387 ppair pair;
00388
00389 pair = pair_new(cube.num_binary_vars);
00390 cand = set_full(cube.num_binary_vars);
00391 total_cost = 0;
00392
00393 while (set_ord(cand) >= 2) {
00394 maxcost = -1;
00395 for(i = 0; i < cube.num_binary_vars; i++) {
00396 if (is_in_set(cand, i)) {
00397 for(j = i+1; j < cube.num_binary_vars; j++) {
00398 if (is_in_set(cand, j)) {
00399 if (cost_array_local[i][j] > maxcost) {
00400 maxcost = cost_array_local[i][j];
00401 besti = i;
00402 bestj = j;
00403 }
00404 }
00405 }
00406 }
00407 }
00408 pair->var1[pair->cnt] = besti+1;
00409 pair->var2[pair->cnt] = bestj+1;
00410 pair->cnt++;
00411 set_remove(cand, besti);
00412 set_remove(cand, bestj);
00413 total_cost += maxcost;
00414 }
00415 set_free(cand);
00416 *pair_p = pair;
00417 return total_cost;
00418 }
00419
00420
00421 ppair pair_best_cost(cost_array_local)
00422 int **cost_array_local;
00423 {
00424 ppair pair;
00425 pset candidate;
00426
00427 best_cost = -1;
00428 best_pair = NULL;
00429 cost_array = cost_array_local;
00430
00431 pair = pair_new(cube.num_binary_vars);
00432 candidate = set_full(cube.num_binary_vars);
00433 generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
00434 pair_free(pair);
00435 set_free(candidate);
00436 return best_pair;
00437 }
00438
00439
00440 int find_best_cost(pair)
00441 register ppair pair;
00442 {
00443 register int i, cost;
00444
00445 cost = 0;
00446 for(i = 0; i < pair->cnt; i++)
00447 cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
00448 if (cost > best_cost) {
00449 best_cost = cost;
00450 best_pair = pair_save(pair, pair->cnt);
00451 }
00452 if ((debug & MINCOV) && trace) {
00453 printf("cost is %d ", cost);
00454 print_pair(pair);
00455 }
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 pair_all(PLA, pair_strategy)
00468 pPLA PLA;
00469 int pair_strategy;
00470 {
00471 ppair pair;
00472 pset candidate;
00473
00474 global_PLA = PLA;
00475 pair_minim_strategy = pair_strategy;
00476 best_cost = PLA->F->count + 1;
00477 best_pair = NULL;
00478 best_phase = NULL;
00479 best_F = best_D = best_R = NULL;
00480 pair = pair_new(cube.num_binary_vars);
00481 candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
00482
00483 generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
00484
00485 pair_free(pair);
00486 set_free(candidate);
00487
00488 PLA->pair = best_pair;
00489 PLA->phase = best_phase;
00490
00491
00492
00493
00494 set_pair(PLA);
00495 printf("# ");
00496 print_pair(PLA->pair);
00497
00498 sf_free(PLA->F);
00499 sf_free(PLA->D);
00500 sf_free(PLA->R);
00501 PLA->F = best_F;
00502 PLA->D = best_D;
00503 PLA->R = best_R;
00504 }
00505
00506
00507
00508
00509
00510 int minimize_pair(pair)
00511 ppair pair;
00512 {
00513 pcover Fsave, Dsave, Rsave;
00514 int i, xnum_binary_vars, xnum_vars, *xpart_size;
00515
00516
00517 Fsave = sf_save(global_PLA->F);
00518 Dsave = sf_save(global_PLA->D);
00519 Rsave = sf_save(global_PLA->R);
00520
00521
00522 xnum_binary_vars = cube.num_binary_vars;
00523 xnum_vars = cube.num_vars;
00524 xpart_size = ALLOC(int, cube.num_vars);
00525 for(i = 0; i < cube.num_vars; i++)
00526 xpart_size[i] = cube.part_size[i];
00527
00528
00529 global_PLA->pair = pair;
00530 set_pair1(global_PLA, FALSE);
00531
00532
00533 if (summary)
00534 print_pair(pair);
00535 switch(pair_minim_strategy) {
00536 case 2:
00537 EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F);
00538 if (summary)
00539 printf("# phase is %s\n", pc1(global_PLA->phase));
00540 break;
00541 case 1:
00542 EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
00543 global_PLA->R, 1), "EXACT ", global_PLA->F);
00544 break;
00545 case 0:
00546 EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
00547 global_PLA->R), "ESPRESSO ", global_PLA->F);
00548 break;
00549 default:
00550 break;
00551 }
00552
00553
00554 if (global_PLA->F->count < best_cost) {
00555 best_cost = global_PLA->F->count;
00556 best_pair = pair_save(pair, pair->cnt);
00557 best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
00558 if (best_F != NULL) sf_free(best_F);
00559 if (best_D != NULL) sf_free(best_D);
00560 if (best_R != NULL) sf_free(best_R);
00561 best_F = sf_save(global_PLA->F);
00562 best_D = sf_save(global_PLA->D);
00563 best_R = sf_save(global_PLA->R);
00564 }
00565
00566
00567 setdown_cube();
00568 FREE(cube.part_size);
00569 cube.num_binary_vars = xnum_binary_vars;
00570 cube.num_vars = xnum_vars;
00571 cube.part_size = xpart_size;
00572 cube_setup();
00573
00574
00575 sf_free(global_PLA->F);
00576 sf_free(global_PLA->D);
00577 sf_free(global_PLA->R);
00578 global_PLA->F = Fsave;
00579 global_PLA->D = Dsave;
00580 global_PLA->R = Rsave;
00581 global_PLA->pair = NULL;
00582 global_PLA->phase = NULL;
00583 }
00584
00585 generate_all_pairs(pair, n, candidate, action)
00586 ppair pair;
00587 int n;
00588 pset candidate;
00589 int (*action)();
00590 {
00591 int i, j;
00592 pset recur_candidate;
00593 ppair recur_pair;
00594
00595 if (set_ord(candidate) < 2) {
00596 (*action)(pair);
00597 return;
00598 }
00599
00600 recur_pair = pair_save(pair, n);
00601 recur_candidate = set_save(candidate);
00602
00603
00604 for(i = 0; i < n; i++)
00605 if (is_in_set(candidate, i))
00606 break;
00607
00608
00609 for(j = i+1; j < n; j++)
00610 if (is_in_set(candidate, j)) {
00611
00612 set_remove(recur_candidate, i);
00613 set_remove(recur_candidate, j);
00614
00615
00616 recur_pair->var1[recur_pair->cnt] = i+1;
00617 recur_pair->var2[recur_pair->cnt] = j+1;
00618 recur_pair->cnt++;
00619
00620
00621 generate_all_pairs(recur_pair, n, recur_candidate, action);
00622
00623
00624 recur_pair->cnt--;
00625 set_insert(recur_candidate, i);
00626 set_insert(recur_candidate, j);
00627 }
00628
00629
00630 if ((set_ord(candidate) % 2) == 1) {
00631 set_remove(recur_candidate, i);
00632 generate_all_pairs(recur_pair, n, recur_candidate, action);
00633 }
00634
00635 pair_free(recur_pair);
00636 set_free(recur_candidate);
00637 }
00638
00639 ppair pair_new(n)
00640 register int n;
00641 {
00642 register ppair pair1;
00643
00644 pair1 = ALLOC(pair_t, 1);
00645 pair1->cnt = 0;
00646 pair1->var1 = ALLOC(int, n);
00647 pair1->var2 = ALLOC(int, n);
00648 return pair1;
00649 }
00650
00651
00652 ppair pair_save(pair, n)
00653 register ppair pair;
00654 register int n;
00655 {
00656 register int k;
00657 register ppair pair1;
00658
00659 pair1 = pair_new(n);
00660 pair1->cnt = pair->cnt;
00661 for(k = 0; k < pair->cnt; k++) {
00662 pair1->var1[k] = pair->var1[k];
00663 pair1->var2[k] = pair->var2[k];
00664 }
00665 return pair1;
00666 }
00667
00668
00669 int pair_free(pair)
00670 register ppair pair;
00671 {
00672 FREE(pair->var1);
00673 FREE(pair->var2);
00674 FREE(pair);
00675 }