license note added, cleaned up per-file doxygen comments and include guards, cleaned...
[libfirm] / ir / adt / hungarian.c
1 /********************************************************************
2  ********************************************************************
3  **
4  ** libhungarian by Cyrill Stachniss, 2004
5  **
6  ** Added and adapted to libFirm by Christian Wuerdig, 2006
7  **
8  ** Solving the Minimum Assignment Problem using the
9  ** Hungarian Method.
10  **
11  ** ** This file may be freely copied and distributed! **
12  **
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!
18  **
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
22  ** PURPOSE.
23  **
24  ********************************************************************
25  ********************************************************************/
26
27 /**
28  * @file
29  * @brief   Solving the Minimum Assignment Problem using the Hungarian Method.
30  * @version $Id$
31  */
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <assert.h>
39
40 #include "irtools.h"
41 #include "xmalloc.h"
42 #include "debug.h"
43 #include "obst.h"
44 #include "bitset.h"
45
46 #include "hungarian.h"
47
48 #define INF (0x7FFFFFFF)
49
50 struct _hungarian_problem_t {
51         int      num_rows;          /**< number of rows */
52         int      num_cols;          /**< number of columns */
53         int      **cost;            /**< the cost matrix */
54         int      width;             /**< the width for cost matrix dumper */
55         int      max_cost;          /**< the maximal costs in the matrix */
56         int      match_type;        /**< PERFECT or NORMAL matching */
57         bitset_t *missing_left;     /**< left side nodes having no edge to the right side */
58         bitset_t *missing_right;    /**< right side nodes having no edge to the left side */
59         struct obstack obst;
60         DEBUG_ONLY(firm_dbg_module_t *dbg);
61 };
62
63 static INLINE void *get_init_mem(struct obstack *obst, long sz) {
64         void *p = obstack_alloc(obst, sz);
65         memset(p, 0, sz);
66         return p;
67 }
68
69 static void hungarian_dump_f(FILE *f, int **C, int rows, int cols, int width) {
70         int i, j;
71
72         fprintf(f , "\n");
73         for (i = 0; i < rows; i++) {
74                 fprintf(f, " [");
75                 for (j = 0; j < cols; j++) {
76                         fprintf(f, "%*d", width, C[i][j]);
77                 }
78                 fprintf(f, "]\n");
79         }
80         fprintf(f, "\n");
81 }
82
83 void hungarian_print_costmatrix(hungarian_problem_t *p) {
84         hungarian_dump_f(stderr, p->cost, p->num_rows, p->num_cols, p->width);
85 }
86
87 /**
88  * Create the object and allocate memory for the data structures.
89  */
90 hungarian_problem_t *hungarian_new(int rows, int cols, int width, int match_type) {
91         int i;
92         hungarian_problem_t *p = xmalloc(sizeof(*p));
93
94         memset(p, 0, sizeof(p[0]));
95
96         FIRM_DBG_REGISTER(p->dbg, "firm.hungarian");
97
98         /*
99                 Is the number of cols  not equal to number of rows ?
100                 If yes, expand with 0 - cols / 0 - cols
101         */
102         rows = MAX(cols, rows);
103         cols = rows;
104
105         obstack_init(&p->obst);
106
107         p->num_rows   = rows;
108         p->num_cols   = cols;
109         p->width      = width;
110         p->match_type = match_type;
111
112         /*
113                 In case of normal matching, we have to keep
114                 track of nodes without edges to kill them in
115                 the assignment later.
116         */
117         if (match_type == HUNGARIAN_MATCH_NORMAL) {
118                 p->missing_left  = bitset_obstack_alloc(&p->obst, rows);
119                 p->missing_right = bitset_obstack_alloc(&p->obst, cols);
120                 bitset_set_all(p->missing_left);
121                 bitset_set_all(p->missing_right);
122         }
123
124         /* allocate space for cost matrix */
125         p->cost = (int **)get_init_mem(&p->obst, rows * sizeof(p->cost[0]));
126         for (i = 0; i < p->num_rows; i++)
127                 p->cost[i] = (int *)get_init_mem(&p->obst, cols * sizeof(p->cost[0][0]));
128
129         return p;
130 }
131
132 /**
133  * Prepare the cost matrix.
134  */
135 void hungarian_prepare_cost_matrix(hungarian_problem_t *p, int mode) {
136         int i, j;
137
138         if (mode == HUNGARIAN_MODE_MAXIMIZE_UTIL) {
139                 for (i = 0; i < p->num_rows; i++) {
140                         for (j = 0; j < p->num_cols; j++) {
141                                 p->cost[i][j] = p->max_cost - p->cost[i][j];
142                         }
143                 }
144         }
145         else if (mode == HUNGARIAN_MODE_MINIMIZE_COST) {
146                 /* nothing to do */
147         }
148         else
149                 fprintf(stderr, "Unknown mode. Mode was set to HUNGARIAN_MODE_MINIMIZE_COST.\n");
150 }
151
152 /**
153  * Set cost[left][right] to cost.
154  */
155 void hungarian_add(hungarian_problem_t *p, int left, int right, int cost) {
156         assert(p->num_rows > left  && "Invalid row selected.");
157         assert(p->num_cols > right && "Invalid column selected.");
158         assert(cost >= 0);
159
160         p->cost[left][right] = cost;
161         p->max_cost          = MAX(p->max_cost, cost);
162
163         if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
164                 bitset_clear(p->missing_left, left);
165                 bitset_clear(p->missing_right, right);
166         }
167 }
168
169 /**
170  * Set cost[left][right] to 0.
171  */
172 void hungarian_remv(hungarian_problem_t *p, int left, int right) {
173         assert(p->num_rows > left  && "Invalid row selected.");
174         assert(p->num_cols > right && "Invalid column selected.");
175
176         p->cost[left][right] = 0;
177
178         if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
179                 bitset_set(p->missing_left, left);
180                 bitset_set(p->missing_right, right);
181         }
182 }
183
184 /**
185  * Frees all allocated memory.
186  */
187 void hungarian_free(hungarian_problem_t* p) {
188         obstack_free(&p->obst, NULL);
189         xfree(p);
190 }
191
192 /**
193  * Do the assignment.
194  */
195 int hungarian_solve(hungarian_problem_t* p, int *assignment, int *final_cost, int cost_threshold) {
196         int i, j, m, n, k, l, s, t, q, unmatched, cost;
197         int *col_mate;
198         int *row_mate;
199         int *parent_row;
200         int *unchosen_row;
201         int *row_dec;
202         int *col_inc;
203         int *slack;
204         int *slack_row;
205
206         cost = 0;
207         m    = p->num_rows;
208         n    = p->num_cols;
209
210         col_mate     = xcalloc(p->num_rows, sizeof(col_mate[0]));
211         unchosen_row = xcalloc(p->num_rows, sizeof(unchosen_row[0]));
212         row_dec      = xcalloc(p->num_rows, sizeof(row_dec[0]));
213         slack_row    = xcalloc(p->num_rows, sizeof(slack_row[0]));
214
215         row_mate     = xcalloc(p->num_cols, sizeof(row_mate[0]));
216         parent_row   = xcalloc(p->num_cols, sizeof(parent_row[0]));
217         col_inc      = xcalloc(p->num_cols, sizeof(col_inc[0]));
218         slack        = xcalloc(p->num_cols, sizeof(slack[0]));
219
220         memset(assignment, -1, m * sizeof(assignment[0]));
221
222         /* Begin subtract column minima in order to start with lots of zeros 12 */
223         DBG((p->dbg, LEVEL_1, "Using heuristic\n"));
224
225         for (l = 0; l < n; ++l) {
226                 s = p->cost[0][l];
227
228                 for (k = 1; k < m; ++k) {
229                         if (p->cost[k][l] < s)
230                                 s = p->cost[k][l];
231                 }
232
233                 cost += s;
234
235                 if (s != 0) {
236                         for (k = 0; k < m; ++k)
237                                 p->cost[k][l] -= s;
238                 }
239         }
240         /* End subtract column minima in order to start with lots of zeros 12 */
241
242         /* Begin initial state 16 */
243         t = 0;
244         for (l = 0; l < n; ++l) {
245                 row_mate[l]   = -1;
246                 parent_row[l] = -1;
247                 col_inc[l]    = 0;
248                 slack[l]      = INF;
249         }
250
251         for (k = 0; k < m; ++k) {
252                 s = p->cost[k][0];
253
254                 for (l = 1; l < n; ++l) {
255                         if (p->cost[k][l] < s)
256                                 s = p->cost[k][l];
257                 }
258
259                 row_dec[k] = s;
260
261                 for (l = 0; l < n; ++l) {
262                         if (s == p->cost[k][l] && row_mate[l] < 0) {
263                                 col_mate[k] = l;
264                                 row_mate[l] = k;
265                                 DBG((p->dbg, LEVEL_1, "matching col %d == row %d\n", l, k));
266                                 goto row_done;
267                         }
268                 }
269
270                 col_mate[k] = -1;
271                 DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, k));
272                 unchosen_row[t++] = k;
273 row_done: ;
274         }
275         /* End initial state 16 */
276
277         /* Begin Hungarian algorithm 18 */
278         if (t == 0)
279                 goto done;
280
281         unmatched = t;
282         while (1) {
283                 DBG((p->dbg, LEVEL_1, "Matched %d rows.\n", m - t));
284                 q = 0;
285
286                 while (1) {
287                         while (q < t) {
288                                 /* Begin explore node q of the forest 19 */
289                                 k = unchosen_row[q];
290                                 s = row_dec[k];
291
292                                 for (l = 0; l < n; ++l) {
293                                         if (slack[l]) {
294                                                 int del = p->cost[k][l] - s + col_inc[l];
295
296                                                 if (del < slack[l]) {
297                                                         if (del == 0) {
298                                                                 if (row_mate[l] < 0)
299                                                                         goto breakthru;
300
301                                                                 slack[l]      = 0;
302                                                                 parent_row[l] = k;
303                                                                 DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[l], l, k));
304                                                                 unchosen_row[t++] = row_mate[l];
305                                                         }
306                                                         else {
307                                                                 slack[l]     = del;
308                                                                 slack_row[l] = k;
309                                                         }
310                                                 }
311                                         }
312                                 }
313                                 /* End explore node q of the forest 19 */
314                                 q++;
315                         }
316
317                         /* Begin introduce a new zero into the matrix 21 */
318                         s = INF;
319                         for (l = 0; l < n; ++l) {
320                                 if (slack[l] && slack[l] < s)
321                                         s = slack[l];
322                         }
323
324                         for (q = 0; q < t; ++q)
325                                 row_dec[unchosen_row[q]] += s;
326
327                         for (l = 0; l < n; ++l) {
328                                 if (slack[l]) {
329                                         slack[l] -= s;
330                                         if (slack[l] == 0) {
331                                                 /* Begin look at a new zero 22 */
332                                                 k = slack_row[l];
333                                                 DBG((p->dbg, LEVEL_1, "Decreasing uncovered elements by %d produces zero at [%d, %d]\n", s, k, l));
334                                                 if (row_mate[l] < 0) {
335                                                         for (j = l + 1; j < n; ++j) {
336                                                                 if (slack[j] == 0)
337                                                                         col_inc[j] += s;
338                                                         }
339                                                         goto breakthru;
340                                                 }
341                                                 else {
342                                                         parent_row[l] = k;
343                                                         DBG((p->dbg, LEVEL_1, "node %d: row %d == col %d -- row %d\n", t, row_mate[l], l, k));
344                                                         unchosen_row[t++] = row_mate[l];
345                                                 }
346                                                 /* End look at a new zero 22 */
347                                         }
348                                 }
349                                 else {
350                                         col_inc[l] += s;
351                                 }
352                         }
353                         /* End introduce a new zero into the matrix 21 */
354                 }
355 breakthru:
356                 /* Begin update the matching 20 */
357                 DBG((p->dbg, LEVEL_1, "Breakthrough at node %d of %d.\n", q, t));
358                 while (1) {
359                         j           = col_mate[k];
360                         col_mate[k] = l;
361                         row_mate[l] = k;
362
363                         DBG((p->dbg, LEVEL_1, "rematching col %d == row %d\n", l, k));
364                         if (j < 0)
365                                 break;
366
367                         k = parent_row[j];
368                         l = j;
369                 }
370                 /* End update the matching 20 */
371
372                 if (--unmatched == 0)
373                         goto done;
374
375                 /* Begin get ready for another stage 17 */
376                 t = 0;
377                 for (l = 0; l < n; ++l) {
378                         parent_row[l] = -1;
379                         slack[l]      = INF;
380                 }
381
382                 for (k = 0; k < m; ++k) {
383                         if (col_mate[k] < 0) {
384                                 DBG((p->dbg, LEVEL_1, "node %d: unmatched row %d\n", t, k));
385                                 unchosen_row[t++] = k;
386                         }
387                 }
388                 /* End get ready for another stage 17 */
389         }
390 done:
391
392         /* Begin double check the solution 23 */
393         for (k = 0; k < m; ++k) {
394                 for (l = 0; l < n; ++l) {
395                         if (p->cost[k][l] < row_dec[k] - col_inc[l])
396                                 return -1;
397                 }
398         }
399
400         for (k = 0; k < m; ++k) {
401                 l = col_mate[k];
402                 if (l < 0 || p->cost[k][l] != row_dec[k] - col_inc[l])
403                         return -2;
404         }
405
406         for (k = l = 0; l < n; ++l) {
407                 if (col_inc[l])
408                         k++;
409         }
410
411         if (k > m)
412                 return -3;
413         /* End double check the solution 23 */
414
415         /* End Hungarian algorithm 18 */
416
417         /* collect the assigned values */
418         for (i = 0; i < m; ++i) {
419                 if (cost_threshold > 0 && p->cost[i][col_mate[i]] >= cost_threshold)
420                         assignment[i] = -1; /* remove matching having cost > threshold */
421                 else
422                         assignment[i] = col_mate[i];
423         }
424
425         /* In case of normal matching: remove impossible ones */
426         if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
427                 for (i = 0; i < m; ++i) {
428                         if (bitset_is_set(p->missing_left, i) || bitset_is_set(p->missing_right, col_mate[i]))
429                                 assignment[i] = -1;
430                 }
431         }
432
433         for (k = 0; k < m; ++k) {
434                 for (l = 0; l < n; ++l) {
435                         p->cost[k][l] = p->cost[k][l] - row_dec[k] + col_inc[l];
436                 }
437         }
438
439         for (i = 0; i < m; ++i)
440                 cost += row_dec[i];
441
442         for (i = 0; i < n; ++i)
443                 cost -= col_inc[i];
444
445         DBG((p->dbg, LEVEL_1, "Cost is %d\n", cost));
446
447         xfree(slack);
448         xfree(col_inc);
449         xfree(parent_row);
450         xfree(row_mate);
451         xfree(slack_row);
452         xfree(row_dec);
453         xfree(unchosen_row);
454         xfree(col_mate);
455
456         *final_cost = cost;
457
458         return 0;
459 }