1 /********************************************************************
2 ********************************************************************
4 ** libhungarian by Cyrill Stachniss, 2004
5 ** -- modified (very) slightly by Benjamin Auder, 2010
6 ** -- (verbose and printing routines deleted, because used in a R package)
9 ** Solving the Minimum Assignment Problem using the
12 ** ** This file may be freely copied and distributed! **
14 ** Parts of the used code was originally provided by the
15 ** "Stanford GraphGase", but I made changes to this code.
16 ** As asked by the copyright node of the "Stanford GraphGase",
17 ** I hereby proclaim that this file are *NOT* part of the
18 ** "Stanford GraphGase" distribution!
20 ** This file is distributed in the hope that it will be useful,
21 ** but WITHOUT ANY WARRANTY; without even the implied
22 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
25 ********************************************************************
26 ********************************************************************/
31 #define HUNGARIAN_NOT_ASSIGNED 0
32 #define HUNGARIAN_ASSIGNED 1
34 #define HUNGARIAN_MODE_MINIMIZE_COST 0
35 #define HUNGARIAN_MODE_MAXIMIZE_UTIL 1
42 } hungarian_problem_t
;
44 #define INF (0x7FFFFFFF)
45 #define hungarian_test_alloc(X) do {if ((void *)(X) == NULL) fprintf(stderr, "Out of memory in %s, (%s, line %d).\n", __FUNCTION__, __FILE__, __LINE__); } while (0)
47 /** This method initialize the hungarian_problem structure and init
48 * the cost matrices (missing lines or columns are filled with 0).
49 * It returns the size of the quadratic(!) assignment matrix. **/
50 void hungarian_init(hungarian_problem_t
* p
, int* cost_matrix
, int rows
, int cols
, int mode
) {
52 int i
,j
, org_cols
, org_rows
;
59 // is the number of cols not equal to number of rows ?
60 // if yes, expand with 0-cols / 0-cols
61 rows
= (cols
< rows
) ? rows
: cols
;
67 p
->cost
= (int**)calloc(rows
,sizeof(int*));
68 hungarian_test_alloc(p
->cost
);
69 p
->assignment
= (int**)calloc(rows
,sizeof(int*));
70 hungarian_test_alloc(p
->assignment
);
72 for(i
=0; i
<p
->num_rows
; i
++) {
73 p
->cost
[i
] = (int*)calloc(cols
,sizeof(int));
74 hungarian_test_alloc(p
->cost
[i
]);
75 p
->assignment
[i
] = (int*)calloc(cols
,sizeof(int));
76 hungarian_test_alloc(p
->assignment
[i
]);
77 for(j
=0; j
<p
->num_cols
; j
++) {
78 p
->cost
[i
][j
] = (i
< org_rows
&& j
< org_cols
) ? cost_matrix
[i
*(p
->num_cols
)+j
] : 0;
79 p
->assignment
[i
][j
] = 0;
81 if (max_cost
< p
->cost
[i
][j
])
82 max_cost
= p
->cost
[i
][j
];
86 if (mode
== HUNGARIAN_MODE_MAXIMIZE_UTIL
) {
87 for(i
=0; i
<p
->num_rows
; i
++) {
88 for(j
=0; j
<p
->num_cols
; j
++) {
89 p
->cost
[i
][j
] = max_cost
- p
->cost
[i
][j
];
95 /** Free the memory allocated by init. **/
96 void hungarian_free(hungarian_problem_t
* p
) {
98 for(i
=0; i
<p
->num_rows
; i
++) {
100 free(p
->assignment
[i
]);
105 p
->assignment
= NULL
;
108 /** This method computes the optimal assignment. **/
109 void hungarian_solve(hungarian_problem_t
* p
) {
111 int i
, j
, m
, n
, k
, l
, s
, t
, q
, unmatched
, cost
;
125 col_mate
= (int*)calloc(p
->num_rows
,sizeof(int));
126 hungarian_test_alloc(col_mate
);
127 unchosen_row
= (int*)calloc(p
->num_rows
,sizeof(int));
128 hungarian_test_alloc(unchosen_row
);
129 row_dec
= (int*)calloc(p
->num_rows
,sizeof(int));
130 hungarian_test_alloc(row_dec
);
131 slack_row
= (int*)calloc(p
->num_rows
,sizeof(int));
132 hungarian_test_alloc(slack_row
);
134 row_mate
= (int*)calloc(p
->num_cols
,sizeof(int));
135 hungarian_test_alloc(row_mate
);
136 parent_row
= (int*)calloc(p
->num_cols
,sizeof(int));
137 hungarian_test_alloc(parent_row
);
138 col_inc
= (int*)calloc(p
->num_cols
,sizeof(int));
139 hungarian_test_alloc(col_inc
);
140 slack
= (int*)calloc(p
->num_cols
,sizeof(int));
141 hungarian_test_alloc(slack
);
143 for (i
=0;i
<p
->num_rows
;i
++) {
149 for (j
=0;j
<p
->num_cols
;j
++) {
156 for (i
=0;i
<p
->num_rows
;++i
)
157 for (j
=0;j
<p
->num_cols
;++j
)
158 p
->assignment
[i
][j
]=HUNGARIAN_NOT_ASSIGNED
;
160 // Begin subtract column minima in order to start with lots of zeroes 12
171 // End subtract column minima in order to start with lots of zeroes 12
173 // Begin initial state 16
188 if (s
==p
->cost
[k
][l
] && row_mate
[l
]<0) {
198 // End initial state 16
200 // Begin Hungarian algorithm 18
208 // Begin explore node q of the forest 19
215 del
=p
->cost
[k
][l
]-s
+col_inc
[l
];
222 unchosen_row
[t
++]=row_mate
[l
];
231 // End explore node q of the forest 19
235 // Begin introduce a new zero into the matrix 21
238 if (slack
[l
] && slack
[l
]<s
)
241 row_dec
[unchosen_row
[q
]]+=s
;
246 // Begin look at a new zero 22
256 unchosen_row
[t
++]=row_mate
[l
];
258 // End look at a new zero 22
263 // End introduce a new zero into the matrix 21
267 // Begin update the matching 20
277 // End update the matching 20
280 // Begin get ready for another stage 17
289 // End get ready for another stage 17
294 // Begin doublecheck the solution 23
297 if (p
->cost
[k
][l
]<row_dec
[k
]-col_inc
[l
])
301 if (l
<0 || p
->cost
[k
][l
]!=row_dec
[k
]-col_inc
[l
])
310 // End doublecheck the solution 23
311 // End Hungarian algorithm 18
314 p
->assignment
[i
][col_mate
[i
]]=HUNGARIAN_ASSIGNED
;
315 /*TRACE("%d - %d\n", i, col_mate[i]);*/
319 p
->cost
[k
][l
]=p
->cost
[k
][l
]-row_dec
[k
]+col_inc
[l
];
337 /* get the optimal assignment, by calling hungarian_solve above */
338 void computeCoefSimil(int* P1
, int* P2
, int* maxInd
, int* n
, double* coefSimil
) {
340 /* first, determine weights by computing intersections
341 * reads like: weights[i*(*n)+j] == gain when cluster i in P1
342 * is assigned to cluster j in P2
345 int* utils
= malloc((*maxInd
) * (*maxInd
) * sizeof(int));
346 for (i
=1; i
<= *maxInd
; i
++) {
347 for (j
=1; j
<= *maxInd
; j
++) {
348 //try label i with label j
350 for (k
=0; k
< *n
; k
++) {
351 if (P1
[k
]==i
&& P2
[k
]==j
) inter
++;
353 utils
[(i
-1)*(*maxInd
)+(j
-1)] = inter
;
357 //then solve problem :
358 hungarian_problem_t p
;
359 hungarian_init(&p
, utils
, *maxInd
, *maxInd
, HUNGARIAN_MODE_MAXIMIZE_UTIL
);
362 //and now get optimal assignment :
364 for (i
=0; i
< *maxInd
; i
++) {
365 for (j
=0; j
< *maxInd
; j
++) {
366 if (p
.assignment
[i
][j
]) *coefSimil
+= utils
[i
*(*maxInd
)+j
];
369 *coefSimil
/= (double)(*n
);