00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014
00015 #include "tree_decomp.h"
00016
00017 td_graph * td_graph_init( long vertex_count, long *state_count, char **matrix ) {
00018 td_graph *graph = (td_graph *)malloc(sizeof(td_graph));
00019
00020 long edge_count = 0;
00021 for (int i = 0; i < vertex_count; i++) {
00022 for (int j = i+1; j < vertex_count; j++) {
00023 if ( matrix[i][j] )
00024 edge_count++;
00025 }
00026 }
00027
00028
00029 graph->vertex_count = vertex_count;
00030 graph->edge_count = edge_count;
00031
00032 if ( state_count != NULL ) {
00033 long cur_loc = 0;
00034 graph->state_count = (long *)malloc(sizeof(long) * vertex_count);
00035 for (int i = 0; i < vertex_count; i++) {
00036 graph->state_count[i] = state_count[i];
00037 cur_loc += state_count[i];
00038 }
00039 graph->vertex_score = (double **)malloc(sizeof(double *) * vertex_count );
00040 graph->vertex_score[0] = (double *)malloc(sizeof(double) * cur_loc );
00041 cur_loc = 0;
00042 for (int i = 0; i < vertex_count; i++) {
00043 graph->vertex_score[i] = graph->vertex_score[0] + cur_loc;
00044 cur_loc += graph->state_count[i];
00045 }
00046 graph->edge_score = (double ***)malloc(sizeof(double **) * vertex_count * vertex_count );
00047 for (int i = 0; i < vertex_count; i++) {
00048 for (int j = 0; j < vertex_count; j++) {
00049 long offset = td_edge_offset( graph, i, j );
00050 if (i < j) {
00051 if ( matrix[i][j] ) {
00052 graph->edge_score[ offset ] = (double **)malloc(sizeof(double *) * state_count[i] );
00053 graph->edge_score[ offset ][0] = (double *)malloc(sizeof(double) * state_count[i] * state_count[j]);
00054 for (int k = 0; k < state_count[i]; k++) {
00055 graph->edge_score[ offset ][k] = graph->edge_score[ offset ][0] + k * state_count[j];
00056 }
00057 } else {
00058 graph->edge_score[ offset ] = NULL;
00059 }
00060 } else {
00061 graph->edge_score[ offset ] = NULL;
00062 }
00063 }
00064 }
00065 }
00066 graph->matrix = matrix;
00067 return graph;
00068 }
00069
00070
00071 char **td_matrix_init( long vertex_count ) {
00072 char **matrix = (char **)malloc(sizeof(char *) * vertex_count );
00073 matrix[0] = (char *)malloc(sizeof(char) * vertex_count * vertex_count);
00074 for (int i = 0; i < vertex_count; i++) {
00075 matrix[i] = matrix[0] + vertex_count * i;
00076 for (int j = 0; j < vertex_count; j++) {
00077 matrix[i][j] = 0;
00078 }
00079 }
00080 return matrix;
00081 }
00082
00083
00084
00085 void td_matrix_free( char ** graph) {
00086 free( graph[0] );
00087 free( graph );
00088 }
00089
00090
00091 void td_graph_free( td_graph *graph) {
00092 free( graph->vertex_score[0] );
00093 free( graph->vertex_score );
00094 free( graph->state_count );
00095 for (int i = 0; i < graph->vertex_count; i++) {
00096 for (int j = 0; j < graph->vertex_count; j++) {
00097 if ( graph->edge_score[i][j] ) {
00098 free( graph->edge_score[ td_edge_offset(graph, i,j) ][0] );
00099 free( graph->edge_score[ td_edge_offset(graph, i,j) ] );
00100 }
00101 }
00102 }
00103 }
00104
00105
00106
00107 long td_dist_count(char **matrix, long matrix_size, long cur_node, long source) {
00108 int i;
00109 long dist = 0, new_dist;
00110 for (i = 0; i < matrix_size; i++) {
00111 if (cur_node != i && i != source && matrix[cur_node][i]) {
00112 new_dist = td_dist_count(matrix, matrix_size, i, cur_node);
00113 if (new_dist > dist)
00114 dist = new_dist;
00115 }
00116 }
00117 return dist + 1;
00118 }
00119
00120 void td_tree_clean_direction( td_decomp *decomp, int cur_bag, int parent) {
00121 for (int i=0; i < decomp->bag_count; i++) {
00122 if ( decomp->bag_matrix[cur_bag][i] ) {
00123 if ( i == cur_bag || i == parent ) {
00124 decomp->bag_matrix[cur_bag][i] = 0;
00125 } else {
00126 td_tree_clean_direction(decomp, i, cur_bag);
00127 }
00128 }
00129 }
00130 }
00131
00132
00133
00134
00135 int bag_intersect( td_decomp *decomp, int bag_1, int bag_2, char *answer ) {
00136 char mask[ decomp->graph->vertex_count ];
00137 int count = 0;
00138 memset(mask, 0x00, decomp->graph->vertex_count );
00139 if (answer != NULL) {
00140 memset(answer, 0x00, decomp->graph->vertex_count );
00141 }
00142 if ( bag_1 != -1) {
00143 for (int i = 0; i < decomp->bag_size[bag_1]; i++) {
00144 mask[ decomp->bag[bag_1][i] ] |= 0x01;
00145 }
00146 }
00147 if ( bag_2 != -1 ) {
00148 for (int i = 0; i < decomp->bag_size[bag_2]; i++) {
00149 mask[ decomp->bag[bag_2][i] ] |= 0x02;
00150 }
00151 }
00152 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00153 if (mask[i] == 0x03) {
00154 if (answer != NULL)
00155 answer[i] = 0x01;
00156 count++;
00157 }
00158 }
00159 return count;
00160 }
00161
00162
00163 char bag_contains_intersect( td_decomp *decomp, int bag_mid, int bag_1, int bag_2 ) {
00164 char mask[ decomp->graph->vertex_count ];
00165 memset(mask, 0x00, decomp->graph->vertex_count );
00166 for (int i = 0; i < decomp->bag_size[bag_1]; i++) {
00167 mask[ decomp->bag[bag_1][i] ] |= 0x01;
00168 }
00169 for (int i = 0; i < decomp->bag_size[bag_2]; i++) {
00170 mask[ decomp->bag[bag_2][i] ] |= 0x02;
00171 }
00172 for (int i = 0; i < decomp->bag_size[bag_mid]; i++) {
00173 mask[ decomp->bag[bag_2][i] ] |= 0x04;
00174 }
00175
00176 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00177 if (mask[i] == 0x03) {
00178 return 0;
00179 }
00180 }
00181 return 1;
00182 }
00183
00184 td_decomp * td_graph_decomp_tri( td_graph *graph ) {
00185 td_decomp *decomp = (td_decomp *)malloc(sizeof(td_decomp));
00186
00187
00188 char **connect_matrix = td_matrix_init( graph->vertex_count );
00189 for (int i = 0; i < graph->vertex_count; i++) {
00190 for (int j = 0; j < graph->vertex_count; j++) {
00191 connect_matrix[i][j] = graph->matrix[i][j];
00192 }
00193 }
00194
00195 char *active_vertex = (char *)malloc(sizeof(char) * graph->vertex_count);
00196 for (int i = 0; i < graph->vertex_count; i++) {
00197 active_vertex[i] = 1;
00198 }
00199
00200 long **bag_list = (long **)malloc(sizeof(long *) * graph->vertex_count);
00201 long *bag_size = (long *)malloc(sizeof(long) * graph->vertex_count);
00202 bag_list[0] =(long *)malloc(sizeof(long) * graph->vertex_count * graph->vertex_count );
00203 for (int i = 0; i < graph->vertex_count; i++) {
00204 bag_size[i] = 0;
00205 bag_list[i] = bag_list[0] + i * (graph->vertex_count);
00206 }
00207
00208 long active_vertex_count = graph->vertex_count;
00209 long bag_count = 0;
00210 long least_edge, least_count;
00211 do {
00212
00213 least_edge = -1;
00214 least_count = 0;
00215 for (int i = 0; i < graph->vertex_count; i++) {
00216 if (active_vertex[i]) {
00217 int connect_count = 0;
00218 for (int j = 0; j < graph->vertex_count; j++) {
00219 if (active_vertex[j] && i != j && connect_matrix[i][j]) {
00220 connect_count++;
00221 }
00222 }
00223 if (least_edge == -1 || least_count > connect_count) {
00224 least_edge = i;
00225 least_count = connect_count;
00226 }
00227 }
00228 }
00229
00230 if (least_edge != -1 && active_vertex_count > least_count) {
00231 active_vertex[least_edge] = 0;
00232 int l = 0;
00233
00234
00235 bag_list[ bag_count ][0] = least_edge;
00236 active_vertex_count--;
00237 l++;
00238
00239 for (int i = 0; i < graph->vertex_count; i++) {
00240 if (active_vertex[i] && connect_matrix[i][least_edge]) {
00241
00242 bag_list[ bag_count ][ l ] = i;
00243 l++;
00244 for (int j = 0; j < graph->vertex_count; j++) {
00245 if (active_vertex[j] && i != j && connect_matrix[j][least_edge]) {
00246 connect_matrix[i][j] = 1;
00247 connect_matrix[j][i] = 1;
00248 }
00249 }
00250 }
00251 }
00252
00253 bag_size[bag_count] = l;
00254 bag_count++;
00255 }
00256 } while (least_edge != -1 && active_vertex_count > least_count);
00257 free(active_vertex);
00258 char **bag_matrix = td_matrix_init( bag_count );
00259
00260 decomp->bag_matrix = bag_matrix;
00261 decomp->bag = bag_list;
00262 decomp->bag_size = bag_size;
00263 decomp->bag_count = bag_count;
00264 decomp->graph = graph;
00265
00266
00267 char *active_bag = (char *)malloc(sizeof(char) * bag_count);
00268 memset(active_bag, 0, sizeof(char) * bag_count);
00269
00270 int active_bag_count = 1;
00271 active_bag[0] = 1;
00272 while ( active_bag_count < bag_count ) {
00273
00274 int max_src = -1, max_dst = -1, max_count = 0;
00275 for (int i = 0; i < bag_count; i++) {
00276 if ( active_bag[i] ) {
00277 for (int j = 0; j < bag_count; j++) {
00278 if ( !active_bag[j] ) {
00279 int set_size = bag_intersect( decomp, i, j, NULL );
00280 if ( set_size > max_count ) {
00281 max_src = i;
00282 max_dst = j;
00283 max_count = set_size;
00284 }
00285 }
00286 }
00287 }
00288 }
00289 if (max_count > 0) {
00290 active_bag[ max_dst ] = 1;
00291 decomp->bag_matrix[max_src][max_dst] = 1;
00292 decomp->bag_matrix[max_dst][max_src] = 1;
00293 active_bag_count++;
00294 } else {
00295 if ( active_bag_count < bag_count ) {
00296
00297
00298 for (int i = 0; i < bag_count; i++) {
00299 if ( !active_bag[i] ) {
00300 for (int j = 0; j < bag_count; j++) {
00301 if (active_bag[j]) {
00302 active_bag[i] = 1;
00303 decomp->bag_matrix[i][j] = 1;
00304 decomp->bag_matrix[j][i] = 1;
00305 active_bag_count++;
00306 i = bag_count;
00307 j = bag_count;
00308 }
00309 }
00310 }
00311 }
00312 }
00313 }
00314 }
00315 free(active_bag);
00316
00317
00318
00319 long dist = -1;
00320 for (int i = 0; i < bag_count; i++) {
00321 int k = td_dist_count(bag_matrix, bag_count, i, -1);
00322 if (dist == -1 || k < dist) {
00323 decomp->root = i;
00324 dist = k;
00325 }
00326 }
00327
00328 decomp->root = 0;
00329
00330
00331 td_tree_clean_direction( decomp, decomp->root, -1);
00332
00333 return decomp;
00334 }
00335
00336
00337 long mask_enum( td_decomp *decomp, char *mask, long *set_pos) {
00338 long out = 0;
00339 long row_size = 1;
00340 int mask_count = 0;
00341 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00342 if (mask[i]) {
00343 out += set_pos[i] * row_size;
00344 row_size *= decomp->graph->state_count[i];
00345 mask_count++;
00346 }
00347 }
00348 if (mask_count == 0) {
00349 return -1;
00350 }
00351 return out;
00352 }
00353
00354 void mask_de_enum( td_decomp *decomp, char *mask, long pos, long *set_pos) {
00355 long in_pos = pos;
00356 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00357 if (mask[i]) {
00358 set_pos[i] = in_pos % decomp->graph->state_count[i];
00359 in_pos = in_pos / decomp->graph->state_count[i];
00360 } else {
00361 set_pos[i] = 0;
00362 }
00363 }
00364 }
00365
00366
00367 typedef struct td_row {
00368 int chosen;
00369 double val;
00370 } td_row;
00371
00372
00373
00374 int td_graph_decomp_extract( td_decomp *decomp, int cur_bag, int parent, td_row **tables, long *sol ) {
00375 if ( parent != -1 ) {
00376 char isec_mask[ decomp->graph->vertex_count ];
00377 bag_intersect( decomp, cur_bag, parent, isec_mask );
00378 long chosen = mask_enum( decomp, isec_mask, sol );
00379
00380 char uniq_mask[ decomp->graph->vertex_count ];
00381 memcpy( uniq_mask, isec_mask, decomp->graph->vertex_count );
00382 for (int i = 0; i < decomp->bag_size[ cur_bag ]; i++) {
00383 if ( ! uniq_mask[ decomp->bag[cur_bag][i] ] ) {
00384 uniq_mask[ decomp->bag[cur_bag][i] ] = 1;
00385 } else {
00386 uniq_mask[ decomp->bag[cur_bag][i] ] = 0;
00387 }
00388 }
00389 for (int i = 0; i < decomp->bag_size[ parent ]; i++) {
00390 uniq_mask[ decomp->bag[parent][i] ] = 0;
00391 }
00392 long sel_pos[ decomp->graph->vertex_count ];
00393 mask_de_enum( decomp, uniq_mask, tables[ cur_bag ][ chosen ].chosen, sel_pos);
00394 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00395 if ( uniq_mask[i] )
00396 sol[i] = sel_pos[i];
00397 }
00398
00399 for (int i = 0; i < decomp->bag_count; i++) {
00400 if ( decomp->bag_matrix[cur_bag][i] ) {
00401 td_graph_decomp_extract( decomp, i, cur_bag, tables, sol);
00402 }
00403 }
00404 } else {
00405 char uniq_mask[ decomp->graph->vertex_count ];
00406 memset(uniq_mask, 0x00, decomp->graph->vertex_count );
00407 for (int i = 0; i < decomp->bag_size[ cur_bag ]; i++) {
00408 uniq_mask[ decomp->bag[cur_bag][i] ] = 1;
00409 }
00410 long cur_pos[ decomp->graph->vertex_count ];
00411 mask_de_enum( decomp, uniq_mask, tables[ cur_bag ][0].chosen, cur_pos );
00412
00413
00414
00415
00416
00417
00418
00419
00420 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00421 if (uniq_mask[i])
00422 sol[i] = cur_pos[i];
00423 }
00424 for (int i = 0; i < decomp->bag_count; i++) {
00425 if ( decomp->bag_matrix[cur_bag][i] ) {
00426 td_graph_decomp_extract( decomp, i, cur_bag, tables, sol);
00427 }
00428 }
00429 }
00430 }
00431
00432
00433
00434 int td_graph_decomp_solve_explore( td_decomp *decomp, int cur_bag, int parent, td_row **tables ) {
00435
00436 for (int i = 0; i < decomp->bag_count; i++) {
00437 if ( decomp->bag_matrix[cur_bag][i] ) {
00438 td_graph_decomp_solve_explore( decomp, i, cur_bag, tables );
00439 }
00440 }
00441
00442
00443
00444 char isec_mask[ decomp->graph->vertex_count ];
00445 int isec_count = bag_intersect( decomp, cur_bag, parent, isec_mask );
00446 long row_count = 1;
00447
00448
00449 if ( isec_count > 0 ) {
00450
00451
00452 row_count = 1;
00453 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00454 if ( isec_mask[i] ) {
00455 row_count *= decomp->graph->state_count[ i ];
00456 }
00457 }
00458 }
00459
00460 tables[ cur_bag ] = (td_row *)malloc( sizeof(td_row) * row_count );
00461
00462
00463
00464 char uniq_mask[ decomp->graph->vertex_count ];
00465 memcpy( uniq_mask, isec_mask, decomp->graph->vertex_count );
00466 for (int i = 0; i < decomp->bag_size[ cur_bag ]; i++) {
00467 if ( ! uniq_mask[ decomp->bag[cur_bag][i] ] ) {
00468 uniq_mask[ decomp->bag[cur_bag][i] ] = 1;
00469 } else {
00470 uniq_mask[ decomp->bag[cur_bag][i] ] = 0;
00471 }
00472 }
00473 if ( parent != -1) {
00474 for (int i = 0; i < decomp->bag_size[ parent ]; i++) {
00475 uniq_mask[ decomp->bag[parent][i] ] = 0;
00476 }
00477 }
00478 int uniq_count = 0;
00479 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00480 if (uniq_mask[i])
00481 uniq_count++;
00482 }
00483
00484
00485 long uniq_row_count = 1;
00486 for (int i = 0; i < decomp->graph->vertex_count; i++) {
00487 if ( uniq_mask[i] ) {
00488 uniq_row_count *= decomp->graph->state_count[ i ];
00489 }
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 char **child_isec = (char **)malloc(sizeof(char *) * decomp->bag_count );
00501 int child_count = 0;
00502 for (int i = 0; i < decomp->bag_count; i++) {
00503 if ( decomp->bag_matrix[cur_bag][i] ) {
00504 child_isec[i] = (char *)malloc(sizeof(char) * decomp->graph->vertex_count);
00505 bag_intersect( decomp, cur_bag, i, child_isec[ i ] );
00506 child_count++;
00507 } else {
00508 child_isec[i] = NULL;
00509 }
00510 }
00511
00512
00513
00514
00515 for (int i = 0; i < row_count; i++) {
00516 long cur_pos[ decomp->graph->vertex_count ];
00517 if ( isec_count > 0 )
00518 mask_de_enum( decomp, isec_mask, i, cur_pos );
00519 else
00520 mask_de_enum( decomp, uniq_mask, i, cur_pos );
00521
00522 int min = -1;
00523 double min_val = 1e20;
00524 for (int j = 0; j < uniq_row_count; j++) {
00525
00526
00527 long row_pos[ decomp->graph->vertex_count ];
00528 mask_de_enum( decomp, uniq_mask, j, row_pos );
00529 double val = 0;
00530 for (int k = 0; k < decomp->graph->vertex_count; k++) {
00531 if (uniq_mask[k]) {
00532 val = decomp->graph->vertex_score[k][ row_pos[k] ];
00533 for (int l = k+1; l < decomp->graph->vertex_count; l++) {
00534 if ( uniq_mask[l] ) {
00535 if ( decomp->graph->matrix[k][l] ) {
00536 int offset = td_edge_offset( decomp->graph, k, l);
00537 val += decomp->graph->edge_score[ offset ][ row_pos[k] ][ row_pos[l] ];
00538
00539 }
00540 }
00541 }
00542 }
00543 }
00544
00545 for (int k = 0; k < decomp->bag_count; k++) {
00546 if ( decomp->bag_matrix[cur_bag][k] ) {
00547 int child_row_num = mask_enum( decomp, child_isec[k], cur_pos);
00548 if ( child_row_num != -1 )
00549 val += tables[ k ][ child_row_num ].val;
00550 }
00551 }
00552 if ( val < min_val ) {
00553 min = j;
00554 min_val = val;
00555 }
00556 }
00557 tables[ cur_bag ][ i ].chosen = min;
00558 tables[ cur_bag ][ i ].val = min_val;
00559 }
00560
00561 for (int i = 0; i < decomp->bag_count; i++) {
00562 if (child_isec[i] != NULL) {
00563 free(child_isec[i]);
00564 }
00565 }
00566 free(child_isec);
00567 }
00568
00569
00570 long *td_graph_decomp_solve( td_decomp *decomp ) {
00571 if ( decomp->bag_count == 0)
00572 return NULL;
00573
00574 td_row **tables = (td_row **)malloc(sizeof(td_row *) * decomp->bag_count );
00575 for (int i = 0; i < decomp->bag_count; i++) {
00576 tables[i] = NULL;
00577 }
00578 td_graph_decomp_solve_explore( decomp, decomp->root, -1, tables );
00579 long *solution = (long *)malloc(sizeof(long) *decomp->graph->vertex_count );
00580 for (int i = 0; i < decomp->graph->vertex_count ; i++) {
00581 solution[i] = -1;
00582 }
00583 td_graph_decomp_extract( decomp, decomp->root, -1, tables, solution );
00584
00585
00586
00587
00588
00589
00590
00591 for (int i = 0; i < decomp->bag_count; i++) {
00592 if ( tables[i] != NULL) {
00593 free( tables[i] );
00594 }
00595 }
00596 return solution;
00597 }