cleanup, simplify hungarian algorithm implementation
authorMatthias Braun <matze@braunis.de>
Mon, 9 Aug 2010 14:52:47 +0000 (14:52 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 9 Aug 2010 14:52:47 +0000 (14:52 +0000)
[r27900]

include/libfirm/adt/hungarian.h
ir/adt/hungarian.c
ir/be/beschedrss.c

index 94be884..fa44bae 100644 (file)
@@ -52,19 +52,20 @@ typedef struct hungarian_problem_t hungarian_problem_t;
  * This method initialize the hungarian_problem structure and init
  * the cost matrix (missing lines or columns are filled with 0).
  *
- * @param rows       Number of rows in the given matrix
- * @param cols       Number of cols in the given matrix
+ * @param num_rows   Number of rows in the given matrix
+ * @param num_cols   Number of cols in the given matrix
  * @param match_type The type of matching
  * @return The problem object.
  */
-FIRM_API hungarian_problem_t *hungarian_new(unsigned rows, unsigned cols,
+FIRM_API hungarian_problem_t *hungarian_new(unsigned num_rows,
+                                            unsigned num_cols,
                                             match_type_t match_type);
 
 /**
  * Adds an edge from left to right with some costs.
  */
 FIRM_API void hungarian_add(hungarian_problem_t *p, unsigned left,
-                            unsigned right, int cost);
+                            unsigned right, unsigned cost);
 
 /**
  * Removes the edge from left to right.
@@ -95,7 +96,7 @@ FIRM_API void hungarian_free(hungarian_problem_t *p);
  * @return 0 on success, negative number otherwise
  */
 FIRM_API int hungarian_solve(hungarian_problem_t *p, unsigned *assignment,
-                             int *final_cost, int cost_threshold);
+                             unsigned *final_cost, unsigned cost_threshold);
 
 /**
  * Print the cost matrix.
index 1b5ebe5..926f768 100644 (file)
 #include "irtools.h"
 #include "xmalloc.h"
 #include "debug.h"
-#include "obst.h"
 #include "bitset.h"
 #include "error.h"
 
 #include "hungarian.h"
 
+DEBUG_ONLY(static firm_dbg_module_t *dbg);
+
 struct hungarian_problem_t {
-       unsigned num_rows;          /**< number of rows */
-       unsigned num_cols;          /**< number of columns */
-       int      **cost;            /**< the cost matrix */
-       int      max_cost;          /**< the maximal costs in the matrix */
-       int      match_type;        /**< PERFECT or NORMAL matching */
-       bitset_t *missing_left;     /**< left side nodes having no edge to the right side */
-       bitset_t *missing_right;    /**< right side nodes having no edge to the left side */
-       struct obstack obst;
-       DEBUG_ONLY(firm_dbg_module_t *dbg);
+       unsigned      num_rows;      /**< number of rows */
+       unsigned      num_cols;      /**< number of columns */
+       unsigned     *cost;          /**< the cost matrix */
+       unsigned      max_cost;      /**< the maximal costs in the matrix */
+       match_type_t  match_type;    /**< PERFECT or NORMAL matching */
+       unsigned     *missing_left;  /**< bitset: left side nodes having no edge to
+                                         the right side */
+       unsigned     *missing_right; /**< bitset: right side nodes having no edge to
+                                     the left side */
 };
 
-static void hungarian_dump_f(FILE *f, int **C, unsigned n_rows, unsigned n_cols,
-                             int width)
+static void hungarian_dump_f(FILE *f, const unsigned *cost,
+                             unsigned num_rows, unsigned num_cols, int width)
 {
-       unsigned r;
+       unsigned r, c;
 
        fprintf(f , "\n");
-       for (r = 0; r < n_rows; r++) {
-               unsigned c;
+       for (r = 0; r < num_rows; r++) {
                fprintf(f, " [");
-               for (c = 0; c < n_cols; c++) {
-                       fprintf(f, "%*d", width, C[r][c]);
+               for (c = 0; c < num_cols; c++) {
+                       fprintf(f, "%*u", width, cost[r*num_cols + c]);
                }
                fprintf(f, "]\n");
        }
@@ -78,25 +78,22 @@ void hungarian_print_cost_matrix(hungarian_problem_t *p, int width)
        hungarian_dump_f(stderr, p->cost, p->num_rows, p->num_cols, width);
 }
 
-hungarian_problem_t *hungarian_new(unsigned n_rows, unsigned n_cols,
+hungarian_problem_t *hungarian_new(unsigned num_rows, unsigned num_cols,
                                    match_type_t match_type)
 {
-       unsigned r;
        hungarian_problem_t *p = XMALLOCZ(hungarian_problem_t);
 
-       FIRM_DBG_REGISTER(p->dbg, "firm.hungarian");
+       FIRM_DBG_REGISTER(dbg, "firm.hungarian");
 
        /*
                Is the number of cols  not equal to number of rows ?
                If yes, expand with 0 - cols / 0 - cols
        */
-       n_rows = MAX(n_cols, n_rows);
-       n_cols = n_rows;
-
-       obstack_init(&p->obst);
+       num_rows = MAX(num_cols, num_rows);
+       num_cols = num_rows;
 
-       p->num_rows   = n_rows;
-       p->num_cols   = n_cols;
+       p->num_rows   = num_rows;
+       p->num_cols   = num_cols;
        p->match_type = match_type;
 
        /*
@@ -105,29 +102,28 @@ hungarian_problem_t *hungarian_new(unsigned n_rows, unsigned n_cols,
                the assignment later.
        */
        if (match_type == HUNGARIAN_MATCH_NORMAL) {
-               p->missing_left  = bitset_obstack_alloc(&p->obst, n_rows);
-               p->missing_right = bitset_obstack_alloc(&p->obst, n_cols);
-               bitset_set_all(p->missing_left);
-               bitset_set_all(p->missing_right);
+               p->missing_left  = rbitset_malloc(num_rows);
+               p->missing_right = rbitset_malloc(num_cols);
+               rbitset_set_all(p->missing_left,  num_rows);
+               rbitset_set_all(p->missing_right, num_cols);
        }
 
        /* allocate space for cost matrix */
-       p->cost = OALLOCNZ(&p->obst, int*, n_rows);
-       for (r = 0; r < p->num_rows; r++)
-               p->cost[r] = OALLOCNZ(&p->obst, int, n_cols);
-
+       p->cost = XMALLOCNZ(unsigned, num_rows * num_cols);
        return p;
 }
 
 void hungarian_prepare_cost_matrix(hungarian_problem_t *p,
                                    hungarian_mode_t mode)
 {
-       unsigned r, c;
-
        if (mode == HUNGARIAN_MODE_MAXIMIZE_UTIL) {
+               unsigned  r, c;
+               unsigned  num_cols = p->num_cols;
+               unsigned *cost     = p->cost;
+               unsigned  max_cost = p->max_cost;
                for (r = 0; r < p->num_rows; r++) {
                        for (c = 0; c < p->num_cols; c++) {
-                               p->cost[r][c] = p->max_cost - p->cost[r][c];
+                               cost[r*num_cols + c] = max_cost - cost[r*num_cols + c];
                        }
                }
        } else if (mode == HUNGARIAN_MODE_MINIMIZE_COST) {
@@ -138,18 +134,17 @@ void hungarian_prepare_cost_matrix(hungarian_problem_t *p,
 }
 
 void hungarian_add(hungarian_problem_t *p, unsigned left, unsigned right,
-                   int cost)
+                   unsigned cost)
 {
        assert(p->num_rows > left  && "Invalid row selected.");
        assert(p->num_cols > right && "Invalid column selected.");
-       assert(cost >= 0);
 
-       p->cost[left][right] = cost;
-       p->max_cost          = MAX(p->max_cost, cost);
+       p->cost[left*p->num_cols + right] = cost;
+       p->max_cost                       = MAX(p->max_cost, cost);
 
        if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
-               bitset_clear(p->missing_left, left);
-               bitset_clear(p->missing_right, right);
+               rbitset_clear(p->missing_left, left);
+               rbitset_clear(p->missing_right, right);
        }
 }
 
@@ -158,35 +153,37 @@ void hungarian_remove(hungarian_problem_t *p, unsigned left, unsigned right)
        assert(p->num_rows > left  && "Invalid row selected.");
        assert(p->num_cols > right && "Invalid column selected.");
 
-       /* Set cost[left][right] to 0. */
-       p->cost[left][right] = 0;
+       p->cost[left*p->num_cols + right] = 0;
 
        if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
-               bitset_set(p->missing_left, left);
-               bitset_set(p->missing_right, right);
+               rbitset_set(p->missing_left, left);
+               rbitset_set(p->missing_right, right);
        }
 }
 
 void hungarian_free(hungarian_problem_t* p)
 {
-       obstack_free(&p->obst, NULL);
+       xfree(p->missing_left);
+       xfree(p->missing_right);
+       xfree(p->cost);
        xfree(p);
 }
 
 int hungarian_solve(hungarian_problem_t* p, unsigned *assignment,
-                    int *final_cost, int cost_threshold)
+                    unsigned *final_cost, unsigned cost_threshold)
 {
-       int       cost          = 0;
-       unsigned  num_rows      = p->num_rows;
-       unsigned  num_cols      = p->num_cols;
-       unsigned *col_mate      = XMALLOCNZ(unsigned, num_rows);
-       unsigned *row_mate      = XMALLOCNZ(unsigned, num_cols);
-       unsigned *parent_row    = XMALLOCNZ(unsigned, num_cols);
-       unsigned *unchosen_row  = XMALLOCNZ(unsigned, num_rows);
-       int      *row_dec       = XMALLOCNZ(int, num_rows);
-       int      *col_inc       = XMALLOCNZ(int, num_cols);
-       int      *slack         = XMALLOCNZ(int, num_cols);
-       unsigned *slack_row     = XMALLOCNZ(unsigned, num_rows);
+       unsigned  res_cost     = 0;
+       unsigned  num_rows     = p->num_rows;
+       unsigned  num_cols     = p->num_cols;
+       unsigned *cost         = p->cost;
+       unsigned *col_mate     = XMALLOCNZ(unsigned, num_rows);
+       unsigned *row_mate     = XMALLOCNZ(unsigned, num_cols);
+       unsigned *parent_row   = XMALLOCNZ(unsigned, num_cols);
+       unsigned *unchosen_row = XMALLOCNZ(unsigned, num_rows);
+       int      *row_dec      = XMALLOCNZ(int, num_rows);
+       int      *col_inc      = XMALLOCNZ(int, num_cols);
+       int      *slack        = XMALLOCNZ(int, num_cols);
+       unsigned *slack_row    = XMALLOCNZ(unsigned, num_rows);
        unsigned  r;
        unsigned  c;
        unsigned  t;
@@ -195,27 +192,27 @@ int hungarian_solve(hungarian_problem_t* p, unsigned *assignment,
        memset(assignment, -1, num_rows * sizeof(assignment[0]));
 
        /* Begin subtract column minima in order to start with lots of zeros 12 */
-       DBG((p->dbg, LEVEL_1, "Using heuristic\n"));
+       DBG((dbg, LEVEL_1, "Using heuristic\n"));
 
        for (c = 0; c < num_cols; ++c) {
-               int s = p->cost[0][c];
+               unsigned col_mininum = cost[0*num_cols + c];
 
                for (r = 1; r < num_rows; ++r) {
-                       if (p->cost[r][c] < s)
-                               s = p->cost[r][c];
+                       if (cost[r*num_cols + c] < col_mininum)
+                               col_mininum = cost[r*num_cols + c];
                }
 
-               cost += s;
-               if (s == 0)
+               if (col_mininum == 0)
                        continue;
 
+               res_cost += col_mininum;
                for (r = 0; r < num_rows; ++r)
-                       p->cost[r][c] -= s;
+                       cost[r*num_cols + c] -= col_mininum;
        }
        /* End subtract column minima in order to start with lots of zeros 12 */
 
        /* Begin initial state 16 */
-       t = 0;
+       unmatched = 0;
        for (c = 0; c < num_cols; ++c) {
                row_mate[c]   = (unsigned) -1;
                parent_row[c] = (unsigned) -1;
@@ -224,40 +221,43 @@ int hungarian_solve(hungarian_problem_t* p, unsigned *assignment,
        }
 
        for (r = 0; r < num_rows; ++r) {
-               int s = p->cost[r][0];
+               unsigned row_minimum = cost[r*num_cols + 0];
 
                for (c = 1; c < num_cols; ++c) {
-                       if (p->cost[r][c] < s)
-                               s = p->cost[r][c];
+                       if (cost[r*num_cols + c] < row_minimum)
+                               row_minimum = cost[r*num_cols + c];
                }
 
-               row_dec[r] = s;
+               row_dec[r] = row_minimum;
 
                for (c = 0; c < num_cols; ++c) {
-                       if (s == p->cost[r][c] && row_mate[c] == (unsigned)-1) {
-                               col_mate[r] = c;
-                               row_mate[c] = r;
-                               DBG((p->dbg, LEVEL_1, "matching col %d == row %d\n", c, r));
-                               goto row_done;
-                       }
+                       if (cost[r*num_cols + c] != row_minimum)
+                               continue;
+                       if (row_mate[c] != (unsigned)-1)
+                               continue;
+
+                       col_mate[r] = c;
+                       row_mate[c] = r;
+                       DBG((dbg, LEVEL_1, "matching col %u == row %u\n", c, r));
+                       goto row_done;
                }
 
                col_mate[r] = (unsigned)-1;
-               DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, r));
-               unchosen_row[t++] = r;
+               DBG((dbg, LEVEL_1, "node %u: unmatched row %u\n", unmatched, r));
+               unchosen_row[unmatched++] = r;
 row_done: ;
        }
        /* End initial state 16 */
 
        /* Begin Hungarian algorithm 18 */
-       if (t == 0)
+       if (unmatched == 0)
                goto done;
 
-       unmatched = t;
+       t = unmatched;
        for (;;) {
                unsigned q = 0;
                unsigned j;
-               DBG((p->dbg, LEVEL_1, "Matched %d rows.\n", num_rows - t));
+               DBG((dbg, LEVEL_1, "Matched %u rows.\n", num_rows - t));
 
                for (;;) {
                        int s;
@@ -268,7 +268,7 @@ row_done: ;
 
                                for (c = 0; c < num_cols; ++c) {
                                        if (slack[c]) {
-                                               int del = p->cost[r][c] - s + col_inc[c];
+                                               int del = cost[r*num_cols + c] - s + col_inc[c];
 
                                                if (del < slack[c]) {
                                                        if (del == 0) {
@@ -277,7 +277,7 @@ row_done: ;
 
                                                                slack[c]      = 0;
                                                                parent_row[c] = r;
-                                                               DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[c], c, r));
+                                                               DBG((dbg, LEVEL_1, "node %u: row %u == col %u -- row %u\n", t, row_mate[c], c, r));
                                                                unchosen_row[t++] = row_mate[c];
                                                        } else {
                                                                slack[c]     = del;
@@ -306,7 +306,7 @@ row_done: ;
                                        if (slack[c] == 0) {
                                                /* Begin look at a new zero 22 */
                                                r = slack_row[c];
-                                               DBG((p->dbg, LEVEL_1, "Decreasing uncovered elements by %d produces zero at [%d, %d]\n", s, r, c));
+                                               DBG((dbg, LEVEL_1, "Decreasing uncovered elements by %d produces zero at [%u, %u]\n", s, r, c));
                                                if (row_mate[c] == (unsigned)-1) {
                                                        for (j = c + 1; j < num_cols; ++j) {
                                                                if (slack[j] == 0)
@@ -315,7 +315,7 @@ row_done: ;
                                                        goto breakthru;
                                                } else {
                                                        parent_row[c] = r;
-                                                       DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[c], c, r));
+                                                       DBG((dbg, LEVEL_1, "node %u: row %u == col %u -- row %u\n", t, row_mate[c], c, r));
                                                        unchosen_row[t++] = row_mate[c];
                                                }
                                                /* End look at a new zero 22 */
@@ -328,13 +328,13 @@ row_done: ;
                }
 breakthru:
                /* Begin update the matching 20 */
-               DBG((p->dbg, LEVEL_1, "Breakthrough at node %d of %d.\n", q, t));
+               DBG((dbg, LEVEL_1, "Breakthrough at node %u of %u.\n", q, t));
                for (;;) {
                        j           = col_mate[r];
                        col_mate[r] = c;
                        row_mate[c] = r;
 
-                       DBG((p->dbg, LEVEL_1, "rematching col %d == row %d\n", c, r));
+                       DBG((dbg, LEVEL_1, "rematching col %u == row %u\n", c, r));
                        if (j == (unsigned)-1)
                                break;
 
@@ -349,13 +349,13 @@ breakthru:
                /* Begin get ready for another stage 17 */
                t = 0;
                for (c = 0; c < num_cols; ++c) {
-                       parent_row[c] = -1;
+                       parent_row[c] = (unsigned) -1;
                        slack[c]      = INT_MAX;
                }
 
                for (r = 0; r < num_rows; ++r) {
                        if (col_mate[r] == (unsigned)-1) {
-                               DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, r));
+                               DBG((dbg, LEVEL_1, "node %u: unmatched row %u\n", t, r));
                                unchosen_row[t++] = r;
                        }
                }
@@ -366,14 +366,15 @@ done:
        /* Begin double check the solution 23 */
        for (r = 0; r < num_rows; ++r) {
                for (c = 0; c < num_cols; ++c) {
-                       if (p->cost[r][c] < row_dec[r] - col_inc[c])
+                       if ((int) cost[r*num_cols + c] < row_dec[r] - col_inc[c])
                                return -1;
                }
        }
 
        for (r = 0; r < num_rows; ++r) {
                c = col_mate[r];
-               if (c == (unsigned)-1 || p->cost[r][c] != row_dec[r] - col_inc[c])
+               if (c == (unsigned)-1
+                   || cost[r*num_cols + c] != (unsigned) (row_dec[r] - col_inc[c]))
                        return -2;
        }
 
@@ -390,7 +391,8 @@ done:
 
        /* collect the assigned values */
        for (r = 0; r < num_rows; ++r) {
-               if (cost_threshold > 0 && p->cost[r][col_mate[r]] >= cost_threshold)
+               if (cost_threshold > 0
+                   && cost[r*num_cols + col_mate[r]] >= cost_threshold)
                        assignment[r] = -1; /* remove matching having cost > threshold */
                else
                        assignment[r] = col_mate[r];
@@ -399,25 +401,25 @@ done:
        /* In case of normal matching: remove impossible ones */
        if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
                for (r = 0; r < num_rows; ++r) {
-                       if (bitset_is_set(p->missing_left, r)
-                               || bitset_is_set(p->missing_right, col_mate[r]))
+                       if (rbitset_is_set(p->missing_left, r)
+                               || rbitset_is_set(p->missing_right, col_mate[r]))
                                assignment[r] = -1;
                }
        }
 
        for (r = 0; r < num_rows; ++r) {
                for (c = 0; c < num_cols; ++c) {
-                       p->cost[r][c] = p->cost[r][c] - row_dec[r] + col_inc[c];
+                       cost[r*num_cols + c] = cost[r*num_cols + c] - row_dec[r] + col_inc[c];
                }
        }
 
        for (r = 0; r < num_rows; ++r)
-               cost += row_dec[r];
+               res_cost += row_dec[r];
 
        for (c = 0; c < num_cols; ++c)
-               cost -= col_inc[c];
+               res_cost -= col_inc[c];
 
-       DBG((p->dbg, LEVEL_1, "Cost is %d\n", cost));
+       DBG((dbg, LEVEL_1, "Cost is %d\n", res_cost));
 
        xfree(slack);
        xfree(col_inc);
@@ -429,7 +431,7 @@ done:
        xfree(col_mate);
 
        if (final_cost != NULL)
-               *final_cost = cost;
+               *final_cost = res_cost;
 
        return 0;
 }
index a889380..0e907b9 100644 (file)
@@ -1495,7 +1495,8 @@ static ir_nodeset_t *compute_maximal_antichain(rss_t *rss, dvg_t *dvg, int itera
        ir_nodeset_iterator_t iter;
        ir_node     *u_irn;
        unsigned    i, j;
-       int         cost, cur_chain, res;
+       unsigned    cost;
+       int         cur_chain, res;
        rss_edge_t  *dvg_edge;
 
 #define MAP_IDX(irn) bsearch_for_index(get_irn_idx(irn), idx_map,  n,  1)
@@ -1595,8 +1596,8 @@ static ir_nodeset_t *compute_maximal_antichain(rss_t *rss, dvg_t *dvg, int itera
                }
        }
 
-       DBG((rss->dbg, LEVEL_2, "\t\tgot assignment with cost %d\n", cost));
-       DBG((rss->dbg, LEVEL_3, "\t\t\tassignment   ---   reverse assignment\n", cost));
+       DBG((rss->dbg, LEVEL_2, "\t\tgot assignment with cost %u\n", cost));
+       DBG((rss->dbg, LEVEL_3, "\t\t\tassignment   ---   reverse assignment\n"));
        for (i = 0; i < n; ++i) {
                DBG((rss->dbg, LEVEL_3, "\t\t\t%3u -> %3u         %3u -> %3u\n", i, assignment[i], i, assignment_rev[i]));
        }