aboutsummaryrefslogtreecommitdiffstats
path: root/package/utils/lua/patches/011-lnum-use-double.patch
blob: 14c720bf1990b5a836d610d920b6aed147788d75 (plain)
1
2
3
4
5
6
7
8
9
10
11
--- a/src/lnum_config.h
+++ b/src/lnum_config.h
@@ -11,7 +11,7 @@
 ** Default number modes
 */
 #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
-# define LNUM_FLOAT
+# define LNUM_DOUBLE
 #endif
 #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
 # define LNUM_INT32
8' href='#n218'>218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
/*
 * Revision Control Information
 *
 * $Source$
 * $Author$
 * $Revision$
 * $Date$
 *
 */
#include "mincov_int.h"

/*
 *  mincov.c
 */

#define USE_GIMPEL
#define USE_INDEP_SET

static int select_column();
static void select_essential();
static int verify_cover();

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

sm_row *
sm_minimum_cover(A, weight, heuristic, debug_level)
sm_matrix *A;
int *weight;
int heuristic;        /* set to 1 for a heuristic covering */
int debug_level;    /* how deep in the recursion to provide info */
{
    stats_t stats;
    solution_t *best, *select;
    sm_row *prow, *sol;
    sm_col *pcol;
    sm_matrix *dup_A;
    int nelem, bound;
    double sparsity;

    /* Avoid sillyness */
    if (A->nrows <= 0) {
    return sm_row_alloc();        /* easy to cover */
    }

    /* Initialize debugging structure */
    stats.start_time = util_cpu_time();
    stats.debug = debug_level > 0;
    stats.max_print_depth = debug_level;
    stats.max_depth = -1;
    stats.nodes = 0;
    stats.component = stats.comp_count = 0;
    stats.gimpel = stats.gimpel_count = 0;
    stats.no_branching = heuristic != 0;
    stats.lower_bound = -1;

    /* Check the matrix sparsity */
    nelem = 0;
    sm_foreach_row(A, prow) {
    nelem += prow->length;
    }
    sparsity = (double) nelem / (double) (A->nrows * A->ncols);

    /* Determine an upper bound on the solution */
    bound = 1;
    sm_foreach_col(A, pcol) {
    bound += WEIGHT(weight, pcol->col_num);
    }

    /* Perform the covering */
    select = solution_alloc();
    dup_A = sm_dup(A);
    best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
    sm_free(dup_A);
    solution_free(select);

    if (stats.debug) {
    if (stats.no_branching) {
        (void) printf("**** heuristic covering ...\n");
        (void) printf("lower bound = %d\n", stats.lower_bound);
    }
    (void) printf("matrix     = %d by %d with %d elements (%4.3f%%)\n",
        A->nrows, A->ncols, nelem, sparsity * 100.0);
    (void) printf("cover size = %d elements\n", best->row->length);
    (void) printf("cover cost = %d\n", best->cost);
    (void) printf("time       = %s\n", 
            util_print_time(util_cpu_time() - stats.start_time));
    (void) printf("components = %d\n", stats.comp_count);
    (void) printf("gimpel     = %d\n", stats.gimpel_count);
    (void) printf("nodes      = %d\n", stats.nodes);
    (void) printf("max_depth  = %d\n", stats.max_depth);
    }

    sol = sm_row_dup(best->row);
    if (! verify_cover(A, sol)) {
    fail("mincov: internal error -- cover verification failed\n");
    }
    solution_free(best);
    return sol;
}

/*
 *  Find the best cover for 'A' (given that 'select' already selected);
 *
 *    - abort search if a solution cannot be found which beats 'bound'
 *
 *    - if any solution meets 'lower_bound', then it is the optimum solution
 *      and can be returned without further work.
 */

solution_t * 
sm_mincov(A, select, weight, lb, bound, depth, stats)
sm_matrix *A;
solution_t *select;
int *weight;
int lb;
int bound;
int depth;
stats_t *stats;
{
    sm_matrix *A1, *A2, *L, *R;
    sm_element *p;
    solution_t *select1, *select2, *best, *best1, *best2, *indep;
    int pick, lb_new, debug;

    /* Start out with some debugging information */
    stats->nodes++;
    if (depth > stats->max_depth) stats->max_depth = depth;
    debug = stats->debug && (depth <= stats->max_print_depth);

    /* Apply row dominance, column dominance, and select essentials */
    select_essential(A, select, weight, bound);
    if (select->cost >= bound) {
    return NIL(solution_t);
    }

    /* See if gimpel's reduction technique applies ... */
#ifdef USE_GIMPEL
    if ( weight == NIL(int)) {    /* hack until we fix it */
    if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
        return best;
    }
    }
#endif

#ifdef USE_INDEP_SET
    /* Determine bound from here to final solution using independent-set */
    indep = sm_maximal_independent_set(A, weight);

    /* make sure the lower bound is monotonically increasing */
    lb_new = MAX(select->cost + indep->cost, lb);
    pick = select_column(A, weight, indep);
    solution_free(indep);
#else
    lb_new = select->cost + (A->nrows > 0);
    pick = select_column(A, weight, NIL(solution_t));
#endif

    if (depth == 0) {
    stats->lower_bound = lb_new + stats->gimpel;
    }

    if (debug) {
        (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
        (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
            A->nrows, A->ncols, select->cost + stats->gimpel, 
        bound + stats->gimpel, lb_new + stats->gimpel, 
        util_print_time(util_cpu_time()-stats->start_time));
    }

    /* Check for bounding based on no better solution possible */
    if (lb_new >= bound) {
    if (debug) (void) printf("bounded\n");
    best = NIL(solution_t);


    /* Check for new best solution */
    } else if (A->nrows == 0) {
    best = solution_dup(select);
    if (debug) (void) printf("BEST\n");
    if (stats->debug && stats->component == 0) {
            (void) printf("new 'best' solution %d at level %d (time is %s)\n", 
        best->cost + stats->gimpel, depth, 
        util_print_time(util_cpu_time() - stats->start_time));
        }


    /* Check for a partition of the problem */
    } else if (sm_block_partition(A, &L, &R)) {
    /* Make L the smaller problem */
    if (L->ncols > R->ncols) {
        A1 = L;
        L = R;
        R = A1;
    }
    if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
    stats->comp_count++;

    /* Solve problem for L */
    select1 = solution_alloc();
    stats->component++;
    best1 = sm_mincov(L, select1, weight, 0, 
                    bound-select->cost, depth+1, stats);
    stats->component--;
    solution_free(select1);
    sm_free(L);

    /* Add best solution to the selected set */
    if (best1 == NIL(solution_t)) {
        best = NIL(solution_t);
    } else {
        for(p = best1->row->first_col; p != 0; p = p->next_col) {
        solution_add(select, weight, p->col_num);
        }
        solution_free(best1);

        /* recur for the remaining block */
        best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
    }
    sm_free(R);

    /* We've tried as hard as possible, but now we must split and recur */
    } else {
    if (debug) (void) printf("pick=%d\n", pick);

        /* Assume we choose this column to be in the covering set */
    A1 = sm_dup(A);
    select1 = solution_dup(select);
    solution_accept(select1, A1, weight, pick);
        best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
    solution_free(select1);
    sm_free(A1);

    /* Update the upper bound if we found a better solution */
    if (best1 != NIL(solution_t) && bound > best1->cost) {
        bound = best1->cost;
    }

    /* See if this is a heuristic covering (no branching) */
    if (stats->no_branching) {
        return best1;
    }

    /* Check for reaching lower bound -- if so, don't actually branch */
    if (best1 != NIL(solution_t) && best1->cost == lb_new) {
        return best1;
    }

        /* Now assume we cannot have that column */
    A2 = sm_dup(A);
    select2 = solution_dup(select);
    solution_reject(select2, A2, weight, pick);
        best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
    solution_free(select2);
    sm_free(A2);

    best = solution_choose_best(best1, best2);
    }

    return best;
}

static int 
select_column(A, weight, indep)
sm_matrix *A;
int *weight;
solution_t *indep;
{
    register sm_col *pcol;
    register sm_row *prow, *indep_cols;
    register sm_element *p, *p1;
    double w, best;
    int best_col;

    indep_cols = sm_row_alloc();
    if (indep != NIL(solution_t)) {
    /* Find which columns are in the independent sets */
    for(p = indep->row->first_col; p != 0; p = p->next_col) {
        prow = sm_get_row(A, p->col_num);
        for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
        (void) sm_row_insert(indep_cols, p1->col_num);
        }
    }
    } else {
    /* select out of all columns */
    sm_foreach_col(A, pcol) {
        (void) sm_row_insert(indep_cols, pcol->col_num);
    }
    }

    /* Find the best column */
    best_col = -1;
    best = -1;

    /* Consider only columns which are in some independent row */
    sm_foreach_row_element(indep_cols, p1) {
    pcol = sm_get_col(A, p1->col_num);

    /* Compute the total 'value' of all things covered by the column */
    w = 0.0;
    for(p = pcol->first_row; p != 0; p = p->next_row) {
        prow = sm_get_row(A, p->row_num);
        w += 1.0 / ((double) prow->length - 1.0);
    }

    /* divide this by the relative cost of choosing this column */
    w = w / (double) WEIGHT(weight, pcol->col_num);

    /* maximize this ratio */
    if (w  > best) {
        best_col = pcol->col_num;
        best = w;
    }
    }

    sm_row_free(indep_cols);
    return best_col;
}

static void 
select_essential(A, select, weight, bound)
sm_matrix *A;
solution_t *select;
int *weight;
int bound;            /* must beat this solution */
{
    register sm_element *p;
    register sm_row *prow, *essen;
    int delcols, delrows, essen_count;

    do {
    /*  Check for dominated columns  */
    delcols = sm_col_dominance(A, weight);

    /*  Find the rows with only 1 element (the essentials) */
    essen = sm_row_alloc();
    sm_foreach_row(A, prow) {
        if (prow->length == 1) {
        (void) sm_row_insert(essen, prow->first_col->col_num);
        }
    }

    /* Select all of the elements */
    sm_foreach_row_element(essen, p) {
        solution_accept(select, A, weight, p->col_num);
        /* Make sure solution still looks good */
        if (select->cost >= bound) {
        sm_row_free(essen);
        return;
        }
    }
    essen_count = essen->length;
    sm_row_free(essen);

    /*  Check for dominated rows  */
    delrows = sm_row_dominance(A);

    } while (delcols > 0 || delrows > 0 || essen_count > 0);
}

static int 
verify_cover(A, cover)
sm_matrix *A;
sm_row *cover;
{
    sm_row *prow;

    sm_foreach_row(A, prow) {
    if (! sm_row_intersects(prow, cover)) {
        return 0;
    }
    }
    return 1;
}