1 /********************************************************************
2 ********************************************************************
4 ** libhungarian by Cyrill Stachniss, 2004
6 ** Added and adapted to libFirm by Christian Wuerdig, 2006
8 ** Solving the Minimum Assignment Problem using the
11 ** ** This file may be freely copied and distributed! **
13 ** Parts of the used code was originally provided by the
14 ** "Stanford GraphGase", but I made changes to this code.
15 ** As asked by the copyright node of the "Stanford GraphGase",
16 ** I hereby proclaim that this file are *NOT* part of the
17 ** "Stanford GraphGase" distrubition!
19 ** This file is distributed in the hope that it will be useful,
20 ** but WITHOUT ANY WARRANTY; without even the implied
21 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
24 ********************************************************************
25 ********************************************************************/
38 #include "hungarian.h"
40 #define INF (0x7FFFFFFF)
42 struct _hungarian_problem_t {
49 DEBUG_ONLY(firm_dbg_module_t *dbg);
52 static INLINE void *get_init_mem(struct obstack *obst, long sz) {
53 void *p = obstack_alloc(obst, sz);
58 static void hungarian_dump_f(FILE *f, int **C, int rows, int cols, int width) {
62 for (i = 0; i < rows; i++) {
64 for (j = 0; j < cols; j++) {
65 fprintf(f, "%*d", width, C[i][j]);
72 void hungarian_print_costmatrix(hungarian_problem_t *p) {
73 hungarian_dump_f(stderr, p->cost, p->num_rows, p->num_cols, p->width);
77 * Create the object and allocate memory for the data structures.
79 hungarian_problem_t *hungarian_new(int rows, int cols, int width) {
82 hungarian_problem_t *p = xmalloc(sizeof(*p));
84 memset(p, 0, sizeof(p));
86 FIRM_DBG_REGISTER(p->dbg, "firm.hungarian");
89 Is the number of cols not equal to number of rows ?
90 If yes, expand with 0 - cols / 0 - cols
92 rows = MAX(cols, rows);
95 obstack_init(&p->obst);
100 p->cost = (int **)get_init_mem(&p->obst, rows * sizeof(p->cost[0]));
102 /* allocate space for cost matrix */
103 for (i = 0; i < p->num_rows; i++)
104 p->cost[i] = (int *)get_init_mem(&p->obst, cols * sizeof(p->cost[0][0]));
110 * Prepare the cost matrix.
112 void hungarian_prepare_cost_matrix(hungarian_problem_t *p, int mode) {
115 if (mode == HUNGARIAN_MODE_MAXIMIZE_UTIL) {
116 for (i = 0; i < p->num_rows; i++) {
117 for (j = 0; j < p->num_cols; j++) {
118 p->cost[i][j] = p->max_cost - p->cost[i][j];
122 else if (mode == HUNGARIAN_MODE_MINIMIZE_COST) {
126 fprintf(stderr, "Unknown mode. Mode was set to HUNGARIAN_MODE_MINIMIZE_COST.\n");
130 * Set cost[left][right] to cost.
132 void hungarian_add(hungarian_problem_t *p, int left, int right, int cost) {
133 assert(p->num_rows > left && "Invalid row selected.");
134 assert(p->num_cols > right && "Invalid column selected.");
136 p->cost[left][right] = cost;
137 p->max_cost = MAX(p->max_cost, cost);
141 * Set cost[left][right] to 0.
143 void hungarian_remv(hungarian_problem_t *p, int left, int right) {
144 assert(p->num_rows > left && "Invalid row selected.");
145 assert(p->num_cols > right && "Invalid column selected.");
147 p->cost[left][right] = 0;
151 * Frees all allocated memory.
153 void hungarian_free(hungarian_problem_t* p) {
154 obstack_free(&p->obst, NULL);
161 int hungarian_solve(hungarian_problem_t* p, int *assignment) {
162 int i, j, m, n, k, l, s, t, q, unmatched, cost;
176 col_mate = xcalloc(p->num_rows, sizeof(col_mate[0]));
177 unchosen_row = xcalloc(p->num_rows, sizeof(unchosen_row[0]));
178 row_dec = xcalloc(p->num_rows, sizeof(row_dec[0]));
179 slack_row = xcalloc(p->num_rows, sizeof(slack_row[0]));
181 row_mate = xcalloc(p->num_cols, sizeof(row_mate[0]));
182 parent_row = xcalloc(p->num_cols, sizeof(parent_row[0]));
183 col_inc = xcalloc(p->num_cols, sizeof(col_inc[0]));
184 slack = xcalloc(p->num_cols, sizeof(slack[0]));
187 for (i = 0; i < p->num_rows; ++i) {
193 for (j=0;j<p->num_cols;j++) {
201 memset(assignment, -1, m * sizeof(assignment[0]));
203 /* Begin subtract column minima in order to start with lots of zeros 12 */
204 DBG((p->dbg, LEVEL_1, "Using heuristic\n"));
206 for (l = 0; l < n; ++l) {
209 for (k = 1; k < m; ++k) {
210 if (p->cost[k][l] < s)
217 for (k = 0; k < m; ++k)
221 /* End subtract column minima in order to start with lots of zeros 12 */
223 /* Begin initial state 16 */
225 for (l = 0; l < n; ++l) {
232 for (k = 0; k < m; ++k) {
235 for (l = 1; l < n; ++l) {
236 if (p->cost[k][l] < s)
242 for (l = 0; l < n; ++l) {
243 if (s == p->cost[k][l] && row_mate[l] < 0) {
246 DBG((p->dbg, LEVEL_1, "matching col %d == row %d\n", l, k));
252 DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, k));
253 unchosen_row[t++] = k;
256 /* End initial state 16 */
258 /* Begin Hungarian algorithm 18 */
264 DBG((p->dbg, LEVEL_1, "Matched %d rows.\n", m - t));
269 /* Begin explore node q of the forest 19 */
273 for (l = 0; l < n; ++l) {
275 int del = p->cost[k][l] - s + col_inc[l];
277 if (del < slack[l]) {
284 DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[l], l, k));
285 unchosen_row[t++] = row_mate[l];
294 /* End explore node q of the forest 19 */
298 /* Begin introduce a new zero into the matrix 21 */
300 for (l = 0; l < n; ++l) {
301 if (slack[l] && slack[l] < s)
305 for (q = 0; q < t; ++q)
306 row_dec[unchosen_row[q]] += s;
308 for (l = 0; l < n; ++l) {
312 /* Begin look at a new zero 22 */
314 DBG((p->dbg, LEVEL_1, "Decreasing uncovered elements by %d produces zero at [%d, %d]\n", s, k, l));
315 if (row_mate[l] < 0) {
316 for (j = l + 1; j < n; ++j) {
324 DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[l], l, k));
325 unchosen_row[t++] = row_mate[l];
327 /* End look at a new zero 22 */
334 /* End introduce a new zero into the matrix 21 */
337 /* Begin update the matching 20 */
338 DBG((p->dbg, LEVEL_1, "Breakthrough at node %d of %d.\n", q, t));
344 DBG((p->dbg, LEVEL_1, "rematching col %d == row %d\n", l, k));
351 /* End update the matching 20 */
353 if (--unmatched == 0)
356 /* Begin get ready for another stage 17 */
358 for (l = 0; l < n; ++l) {
363 for (k = 0; k < m; ++k) {
364 if (col_mate[k] < 0) {
365 DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, k));
366 unchosen_row[t++] = k;
369 /* End get ready for another stage 17 */
373 /* Begin double check the solution 23 */
374 for (k = 0; k < m; ++k) {
375 for (l = 0; l < n; ++l) {
376 if (p->cost[k][l] < row_dec[k] - col_inc[l])
381 for (k = 0; k < m; ++k) {
383 if (l < 0 || p->cost[k][l] != row_dec[k] - col_inc[l])
387 for (k = l = 0; l < n; ++l) {
394 /* End double check the solution 23 */
396 /* End Hungarian algorithm 18 */
398 /* collect the assigned values */
399 for (i = 0; i < m; ++i) {
400 assignment[i] = col_mate[i];
403 for (k = 0; k < m; ++k) {
404 for (l = 0; l < n; ++l) {
405 p->cost[k][l] = p->cost[k][l] - row_dec[k] + col_inc[l];
409 for (i = 0; i < m; ++i)
412 for (i = 0; i < n; ++i)
415 DBG((p->dbg, LEVEL_1, "Cost is %d\n", cost));