src/misc/espresso/mincov.c File Reference

#include "mincov_int.h"
Include dependency graph for mincov.c:

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_rowsm_minimum_cover (sm_matrix *A, int *weight, int heuristic, int debug_level)
solution_tsm_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 Documentation

#define fail ( why   ) 
Value:
{\
    (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
        __FILE__, __LINE__, why);\
    (void) fflush(stdout);\
    abort();\
}

Definition at line 23 of file mincov.c.

#define USE_GIMPEL

Definition at line 16 of file mincov.c.

#define USE_INDEP_SET

Definition at line 17 of file mincov.c.


Function Documentation

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 }

sm_row* sm_minimum_cover ( sm_matrix A,
int *  weight,
int  heuristic,
int  debug_level 
)

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 }

static int verify_cover ( sm_matrix A,
sm_row cover 
) [static]

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]

Generated on Tue Jan 5 12:19:11 2010 for abc70930 by  doxygen 1.6.1