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