1 /********************************************************************
2 ********************************************************************
4 ** libhungarian by Cyrill Stachniss, 2004
5 ** Modified by Benjamin Auder to work on floating point number,
6 ** and to fit into a R package (2017)
8 ** Solving the Minimum Assignment Problem using the Hungarian Method.
10 ** ** This file may be freely copied and distributed! **
12 ** Parts of the used code was originally provided by the
13 ** "Stanford GraphGase", but I made changes to this code.
14 ** As asked by the copyright node of the "Stanford GraphGase",
15 ** I hereby proclaim that this file are *NOT* part of the
16 ** "Stanford GraphGase" distrubition!
18 ** This file is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied
20 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
23 ********************************************************************
24 ********************************************************************/
29 #define HUNGARIAN_NOT_ASSIGNED 0
30 #define HUNGARIAN_ASSIGNED 1
32 #define HUNGARIAN_MODE_MINIMIZE_COST 0
33 #define HUNGARIAN_MODE_MAXIMIZE_UTIL 1
43 } hungarian_problem_t
;
45 int hungarian_imax(int a
, int b
) {
49 /** This method initialize the hungarian_problem structure and init
50 * the cost matrices (missing lines or columns are filled with 0).
51 * It returns the size of the quadratic(!) assignment matrix. **/
52 int hungarian_init(hungarian_problem_t
* p
, double** cost_matrix
, int rows
, int cols
,
60 // is the number of cols not equal to number of rows ?
61 // if yes, expand with 0-cols / 0-cols
62 rows
= hungarian_imax(cols
, rows
);
68 p
->cost
= (double**)calloc(rows
,sizeof(double*));
69 p
->assignment
= (int**)calloc(rows
,sizeof(int*));
71 for(i
=0; i
<p
->num_rows
; i
++) {
72 p
->cost
[i
] = (double*)calloc(cols
,sizeof(double));
73 p
->assignment
[i
] = (int*)calloc(cols
,sizeof(int));
74 for(j
=0; j
<p
->num_cols
; j
++) {
75 p
->cost
[i
][j
] = (i
< org_rows
&& j
< org_cols
) ? cost_matrix
[i
][j
] : 0.;
76 p
->assignment
[i
][j
] = 0;
78 if (max_cost
< p
->cost
[i
][j
])
79 max_cost
= p
->cost
[i
][j
];
83 if (mode
== HUNGARIAN_MODE_MAXIMIZE_UTIL
) {
84 for(i
=0; i
<p
->num_rows
; i
++) {
85 for(j
=0; j
<p
->num_cols
; j
++)
86 p
->cost
[i
][j
] = max_cost
- p
->cost
[i
][j
];
89 else if (mode
== HUNGARIAN_MODE_MINIMIZE_COST
) {
93 // fprintf(stderr,"%s: unknown mode. Mode was set to \
94 // HUNGARIAN_MODE_MINIMIZE_COST !\n", __FUNCTION__);
99 /** Free the memory allocated by init. **/
100 void hungarian_free(hungarian_problem_t
* p
) {
102 for(i
=0; i
<p
->num_rows
; i
++) {
104 free(p
->assignment
[i
]);
109 p
->assignment
= NULL
;
112 /** This method computes the optimal assignment. **/
113 void hungarian_solve(hungarian_problem_t
* p
)
115 int i
, j
, m
, n
, k
, l
, t
, q
, unmatched
;
130 col_mate
= (int*)calloc(p
->num_rows
,sizeof(int));
131 unchosen_row
= (int*)calloc(p
->num_rows
,sizeof(int));
132 row_dec
= (double*)calloc(p
->num_rows
,sizeof(double));
133 slack_row
= (int*)calloc(p
->num_rows
,sizeof(int));
135 row_mate
= (int*)calloc(p
->num_cols
,sizeof(int));
136 parent_row
= (int*)calloc(p
->num_cols
,sizeof(int));
137 col_inc
= (double*)calloc(p
->num_cols
,sizeof(double));
138 slack
= (double*)calloc(p
->num_cols
,sizeof(double));
140 for (i
=0; i
<p
->num_rows
; i
++) {
146 for (j
=0; j
<p
->num_cols
; j
++) {
153 for (i
=0; i
<p
->num_rows
; ++i
)
154 for (j
=0; j
<p
->num_cols
; ++j
)
155 p
->assignment
[i
][j
]=HUNGARIAN_NOT_ASSIGNED
;
157 // Begin subtract column minima in order to start with lots of zeroes 12
169 // End subtract column minima in order to start with lots of zeroes 12
171 // Begin initial state 16
188 if (s
==p
->cost
[k
][l
] && row_mate
[l
]<0)
199 // End initial state 16
201 // Begin Hungarian algorithm 18
212 // Begin explore node q of the forest 19
219 double del
=p
->cost
[k
][l
]-s
+col_inc
[l
];
228 unchosen_row
[t
++]=row_mate
[l
];
238 // End explore node q of the forest 19
242 // Begin introduce a new zero into the matrix 21
245 if (slack
[l
]>0. && slack
[l
]<s
)
248 row_dec
[unchosen_row
[q
]]+=s
;
255 // Begin look at a new zero 22
259 for (j
=l
+1; j
<n
; j
++)
267 unchosen_row
[t
++]=row_mate
[l
];
269 // End look at a new zero 22
274 // End introduce a new zero into the matrix 21
277 // Begin update the matching 20
288 // End update the matching 20
291 // Begin get ready for another stage 17
301 // End get ready for another stage 17
305 /* // Begin doublecheck the solution 23
308 if (p->cost[k][l]<row_dec[k]-col_inc[l])
313 if (l<0 || p->cost[k][l]!=row_dec[k]-col_inc[l])
322 // End doublecheck the solution 23
323 */ // End Hungarian algorithm 18
327 p
->assignment
[i
][col_mate
[i
]]=HUNGARIAN_ASSIGNED
;
328 /*TRACE("%d - %d\n", i, col_mate[i]);*/
334 /*TRACE("%d ",p->cost[k][l]-row_dec[k]+col_inc[l]);*/
335 p
->cost
[k
][l
]=p
->cost
[k
][l
]-row_dec
[k
]+col_inc
[l
];
359 // Auxiliary function for hungarianAlgorithm below
360 double** array_to_matrix(double* m
, int rows
, int cols
)
362 double** r
= (double**)calloc(rows
,sizeof(double*));
363 for (int i
=0; i
<rows
; i
++)
365 r
[i
] = (double*)calloc(cols
,sizeof(double));
366 for (int j
=0; j
<cols
; j
++)
367 r
[i
][j
] = m
[i
*cols
+j
];
372 //TODO: re-code this algorithm in a more readable way, based on
373 //https://www.topcoder.com/community/data-science/data-science-tutorials/\
374 // assignment-problem-and-hungarian-algorithm/
375 // Get the optimal assignment, by calling hungarian_solve above; "distances" in columns
376 void hungarianAlgorithm(double* distances
, int* pn
, int* assignment
)
379 double** mat
= array_to_matrix(distances
, n
, n
);
381 hungarian_problem_t p
;
382 hungarian_init(&p
, mat
, n
, n
, HUNGARIAN_MODE_MINIMIZE_COST
);
386 // Copy the optimal assignment in a R-friendly structure
387 for (int i
=0; i
< n
; i
++) {
388 for (int j
=0; j
< n
; j
++) {
389 if (p
.assignment
[i
][j
])
390 assignment
[i
] = j
+1; //add 1 since we work with R
395 for (int i
=0; i
<n
; i
++)