#include "mincov_int.h"
Go to the source code of this file.
Defines | |
#define | USE_GIMPEL |
#define | USE_INDEP_SET |
#define | fail(why) |
Functions | |
static int | select_column () |
static void | select_essential () |
static int | verify_cover () |
sm_row * | sm_minimum_cover (sm_matrix *A, int *weight, int heuristic, int debug_level) |
solution_t * | sm_mincov (sm_matrix *A, solution_t *select, int *weight, int lb, int bound, int depth, stats_t *stats) |
static int | select_column (sm_matrix *A, int *weight, solution_t *indep) |
static void | select_essential (sm_matrix *A, solution_t *select, int *weight, int bound) |
static int | verify_cover (sm_matrix *A, sm_row *cover) |
#define fail | ( | why | ) |
static int select_column | ( | sm_matrix * | A, | |
int * | weight, | |||
solution_t * | indep | |||
) | [static] |
Definition at line 268 of file mincov.c.
00272 { 00273 register sm_col *pcol; 00274 register sm_row *prow, *indep_cols; 00275 register sm_element *p, *p1; 00276 double w, best; 00277 int best_col; 00278 00279 indep_cols = sm_row_alloc(); 00280 if (indep != NIL(solution_t)) { 00281 /* Find which columns are in the independent sets */ 00282 for(p = indep->row->first_col; p != 0; p = p->next_col) { 00283 prow = sm_get_row(A, p->col_num); 00284 for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) { 00285 (void) sm_row_insert(indep_cols, p1->col_num); 00286 } 00287 } 00288 } else { 00289 /* select out of all columns */ 00290 sm_foreach_col(A, pcol) { 00291 (void) sm_row_insert(indep_cols, pcol->col_num); 00292 } 00293 } 00294 00295 /* Find the best column */ 00296 best_col = -1; 00297 best = -1; 00298 00299 /* Consider only columns which are in some independent row */ 00300 sm_foreach_row_element(indep_cols, p1) { 00301 pcol = sm_get_col(A, p1->col_num); 00302 00303 /* Compute the total 'value' of all things covered by the column */ 00304 w = 0.0; 00305 for(p = pcol->first_row; p != 0; p = p->next_row) { 00306 prow = sm_get_row(A, p->row_num); 00307 w += 1.0 / ((double) prow->length - 1.0); 00308 } 00309 00310 /* divide this by the relative cost of choosing this column */ 00311 w = w / (double) WEIGHT(weight, pcol->col_num); 00312 00313 /* maximize this ratio */ 00314 if (w > best) { 00315 best_col = pcol->col_num; 00316 best = w; 00317 } 00318 } 00319 00320 sm_row_free(indep_cols); 00321 return best_col; 00322 }
static int select_column | ( | ) | [static] |
static void select_essential | ( | sm_matrix * | A, | |
solution_t * | select, | |||
int * | weight, | |||
int | bound | |||
) | [static] |
Definition at line 325 of file mincov.c.
00330 { 00331 register sm_element *p; 00332 register sm_row *prow, *essen; 00333 int delcols, delrows, essen_count; 00334 00335 do { 00336 /* Check for dominated columns */ 00337 delcols = sm_col_dominance(A, weight); 00338 00339 /* Find the rows with only 1 element (the essentials) */ 00340 essen = sm_row_alloc(); 00341 sm_foreach_row(A, prow) { 00342 if (prow->length == 1) { 00343 (void) sm_row_insert(essen, prow->first_col->col_num); 00344 } 00345 } 00346 00347 /* Select all of the elements */ 00348 sm_foreach_row_element(essen, p) { 00349 solution_accept(select, A, weight, p->col_num); 00350 /* Make sure solution still looks good */ 00351 if (select->cost >= bound) { 00352 sm_row_free(essen); 00353 return; 00354 } 00355 } 00356 essen_count = essen->length; 00357 sm_row_free(essen); 00358 00359 /* Check for dominated rows */ 00360 delrows = sm_row_dominance(A); 00361 00362 } while (delcols > 0 || delrows > 0 || essen_count > 0); 00363 }
static void select_essential | ( | ) | [static] |
solution_t* sm_mincov | ( | sm_matrix * | A, | |
solution_t * | select, | |||
int * | weight, | |||
int | lb, | |||
int | bound, | |||
int | depth, | |||
stats_t * | stats | |||
) |
Definition at line 116 of file mincov.c.
00124 { 00125 sm_matrix *A1, *A2, *L, *R; 00126 sm_element *p; 00127 solution_t *select1, *select2, *best, *best1, *best2, *indep; 00128 int pick, lb_new, debug; 00129 00130 /* Start out with some debugging information */ 00131 stats->nodes++; 00132 if (depth > stats->max_depth) stats->max_depth = depth; 00133 debug = stats->debug && (depth <= stats->max_print_depth); 00134 00135 /* Apply row dominance, column dominance, and select essentials */ 00136 select_essential(A, select, weight, bound); 00137 if (select->cost >= bound) { 00138 return NIL(solution_t); 00139 } 00140 00141 /* See if gimpel's reduction technique applies ... */ 00142 #ifdef USE_GIMPEL 00143 if ( weight == NIL(int)) { /* hack until we fix it */ 00144 if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) { 00145 return best; 00146 } 00147 } 00148 #endif 00149 00150 #ifdef USE_INDEP_SET 00151 /* Determine bound from here to final solution using independent-set */ 00152 indep = sm_maximal_independent_set(A, weight); 00153 00154 /* make sure the lower bound is monotonically increasing */ 00155 lb_new = MAX(select->cost + indep->cost, lb); 00156 pick = select_column(A, weight, indep); 00157 solution_free(indep); 00158 #else 00159 lb_new = select->cost + (A->nrows > 0); 00160 pick = select_column(A, weight, NIL(solution_t)); 00161 #endif 00162 00163 if (depth == 0) { 00164 stats->lower_bound = lb_new + stats->gimpel; 00165 } 00166 00167 if (debug) { 00168 (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " "); 00169 (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ", 00170 A->nrows, A->ncols, select->cost + stats->gimpel, 00171 bound + stats->gimpel, lb_new + stats->gimpel, 00172 util_print_time(util_cpu_time()-stats->start_time)); 00173 } 00174 00175 /* Check for bounding based on no better solution possible */ 00176 if (lb_new >= bound) { 00177 if (debug) (void) printf("bounded\n"); 00178 best = NIL(solution_t); 00179 00180 00181 /* Check for new best solution */ 00182 } else if (A->nrows == 0) { 00183 best = solution_dup(select); 00184 if (debug) (void) printf("BEST\n"); 00185 if (stats->debug && stats->component == 0) { 00186 (void) printf("new 'best' solution %d at level %d (time is %s)\n", 00187 best->cost + stats->gimpel, depth, 00188 util_print_time(util_cpu_time() - stats->start_time)); 00189 } 00190 00191 00192 /* Check for a partition of the problem */ 00193 } else if (sm_block_partition(A, &L, &R)) { 00194 /* Make L the smaller problem */ 00195 if (L->ncols > R->ncols) { 00196 A1 = L; 00197 L = R; 00198 R = A1; 00199 } 00200 if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows); 00201 stats->comp_count++; 00202 00203 /* Solve problem for L */ 00204 select1 = solution_alloc(); 00205 stats->component++; 00206 best1 = sm_mincov(L, select1, weight, 0, 00207 bound-select->cost, depth+1, stats); 00208 stats->component--; 00209 solution_free(select1); 00210 sm_free(L); 00211 00212 /* Add best solution to the selected set */ 00213 if (best1 == NIL(solution_t)) { 00214 best = NIL(solution_t); 00215 } else { 00216 for(p = best1->row->first_col; p != 0; p = p->next_col) { 00217 solution_add(select, weight, p->col_num); 00218 } 00219 solution_free(best1); 00220 00221 /* recur for the remaining block */ 00222 best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats); 00223 } 00224 sm_free(R); 00225 00226 /* We've tried as hard as possible, but now we must split and recur */ 00227 } else { 00228 if (debug) (void) printf("pick=%d\n", pick); 00229 00230 /* Assume we choose this column to be in the covering set */ 00231 A1 = sm_dup(A); 00232 select1 = solution_dup(select); 00233 solution_accept(select1, A1, weight, pick); 00234 best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats); 00235 solution_free(select1); 00236 sm_free(A1); 00237 00238 /* Update the upper bound if we found a better solution */ 00239 if (best1 != NIL(solution_t) && bound > best1->cost) { 00240 bound = best1->cost; 00241 } 00242 00243 /* See if this is a heuristic covering (no branching) */ 00244 if (stats->no_branching) { 00245 return best1; 00246 } 00247 00248 /* Check for reaching lower bound -- if so, don't actually branch */ 00249 if (best1 != NIL(solution_t) && best1->cost == lb_new) { 00250 return best1; 00251 } 00252 00253 /* Now assume we cannot have that column */ 00254 A2 = sm_dup(A); 00255 select2 = solution_dup(select); 00256 solution_reject(select2, A2, weight, pick); 00257 best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats); 00258 solution_free(select2); 00259 sm_free(A2); 00260 00261 best = solution_choose_best(best1, best2); 00262 } 00263 00264 return best; 00265 }
Definition at line 31 of file mincov.c.
00036 { 00037 stats_t stats; 00038 solution_t *best, *select; 00039 sm_row *prow, *sol; 00040 sm_col *pcol; 00041 sm_matrix *dup_A; 00042 int nelem, bound; 00043 double sparsity; 00044 00045 /* Avoid sillyness */ 00046 if (A->nrows <= 0) { 00047 return sm_row_alloc(); /* easy to cover */ 00048 } 00049 00050 /* Initialize debugging structure */ 00051 stats.start_time = util_cpu_time(); 00052 stats.debug = debug_level > 0; 00053 stats.max_print_depth = debug_level; 00054 stats.max_depth = -1; 00055 stats.nodes = 0; 00056 stats.component = stats.comp_count = 0; 00057 stats.gimpel = stats.gimpel_count = 0; 00058 stats.no_branching = heuristic != 0; 00059 stats.lower_bound = -1; 00060 00061 /* Check the matrix sparsity */ 00062 nelem = 0; 00063 sm_foreach_row(A, prow) { 00064 nelem += prow->length; 00065 } 00066 sparsity = (double) nelem / (double) (A->nrows * A->ncols); 00067 00068 /* Determine an upper bound on the solution */ 00069 bound = 1; 00070 sm_foreach_col(A, pcol) { 00071 bound += WEIGHT(weight, pcol->col_num); 00072 } 00073 00074 /* Perform the covering */ 00075 select = solution_alloc(); 00076 dup_A = sm_dup(A); 00077 best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats); 00078 sm_free(dup_A); 00079 solution_free(select); 00080 00081 if (stats.debug) { 00082 if (stats.no_branching) { 00083 (void) printf("**** heuristic covering ...\n"); 00084 (void) printf("lower bound = %d\n", stats.lower_bound); 00085 } 00086 (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n", 00087 A->nrows, A->ncols, nelem, sparsity * 100.0); 00088 (void) printf("cover size = %d elements\n", best->row->length); 00089 (void) printf("cover cost = %d\n", best->cost); 00090 (void) printf("time = %s\n", 00091 util_print_time(util_cpu_time() - stats.start_time)); 00092 (void) printf("components = %d\n", stats.comp_count); 00093 (void) printf("gimpel = %d\n", stats.gimpel_count); 00094 (void) printf("nodes = %d\n", stats.nodes); 00095 (void) printf("max_depth = %d\n", stats.max_depth); 00096 } 00097 00098 sol = sm_row_dup(best->row); 00099 if (! verify_cover(A, sol)) { 00100 fail("mincov: internal error -- cover verification failed\n"); 00101 } 00102 solution_free(best); 00103 return sol; 00104 }
Definition at line 366 of file mincov.c.
00369 { 00370 sm_row *prow; 00371 00372 sm_foreach_row(A, prow) { 00373 if (! sm_row_intersects(prow, cover)) { 00374 return 0; 00375 } 00376 } 00377 return 1; 00378 }
static int verify_cover | ( | ) | [static] |