Mercurial > hg > camir-aes2014
comparison toolboxes/FullBNT-1.0.7/KPMtools/hungarian.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function [C,T]=hungarian(A) | |
2 %HUNGARIAN Solve the Assignment problem using the Hungarian method. | |
3 % | |
4 %[C,T]=hungarian(A) | |
5 %A - a square cost matrix. | |
6 %C - the optimal assignment. | |
7 %T - the cost of the optimal assignment. | |
8 | |
9 % Adapted from the FORTRAN IV code in Carpaneto and Toth, "Algorithm 548: | |
10 % Solution of the assignment problem [H]", ACM Transactions on | |
11 % Mathematical Software, 6(1):104-111, 1980. | |
12 | |
13 % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. | |
14 % Department of Computing Science, Umeå University, | |
15 % Sweden. | |
16 % All standard disclaimers apply. | |
17 | |
18 % A substantial effort was put into this code. If you use it for a | |
19 % publication or otherwise, please include an acknowledgement or at least | |
20 % notify me by email. /Niclas | |
21 | |
22 [m,n]=size(A); | |
23 | |
24 if (m~=n) | |
25 error('HUNGARIAN: Cost matrix must be square!'); | |
26 end | |
27 | |
28 % Save original cost matrix. | |
29 orig=A; | |
30 | |
31 % Reduce matrix. | |
32 A=hminired(A); | |
33 | |
34 % Do an initial assignment. | |
35 [A,C,U]=hminiass(A); | |
36 | |
37 % Repeat while we have unassigned rows. | |
38 while (U(n+1)) | |
39 % Start with no path, no unchecked zeros, and no unexplored rows. | |
40 LR=zeros(1,n); | |
41 LC=zeros(1,n); | |
42 CH=zeros(1,n); | |
43 RH=[zeros(1,n) -1]; | |
44 | |
45 % No labelled columns. | |
46 SLC=[]; | |
47 | |
48 % Start path in first unassigned row. | |
49 r=U(n+1); | |
50 % Mark row with end-of-path label. | |
51 LR(r)=-1; | |
52 % Insert row first in labelled row set. | |
53 SLR=r; | |
54 | |
55 % Repeat until we manage to find an assignable zero. | |
56 while (1) | |
57 % If there are free zeros in row r | |
58 if (A(r,n+1)~=0) | |
59 % ...get column of first free zero. | |
60 l=-A(r,n+1); | |
61 | |
62 % If there are more free zeros in row r and row r in not | |
63 % yet marked as unexplored.. | |
64 if (A(r,l)~=0 & RH(r)==0) | |
65 % Insert row r first in unexplored list. | |
66 RH(r)=RH(n+1); | |
67 RH(n+1)=r; | |
68 | |
69 % Mark in which column the next unexplored zero in this row | |
70 % is. | |
71 CH(r)=-A(r,l); | |
72 end | |
73 else | |
74 % If all rows are explored.. | |
75 if (RH(n+1)<=0) | |
76 % Reduce matrix. | |
77 [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR); | |
78 end | |
79 | |
80 % Re-start with first unexplored row. | |
81 r=RH(n+1); | |
82 % Get column of next free zero in row r. | |
83 l=CH(r); | |
84 % Advance "column of next free zero". | |
85 CH(r)=-A(r,l); | |
86 % If this zero is last in the list.. | |
87 if (A(r,l)==0) | |
88 % ...remove row r from unexplored list. | |
89 RH(n+1)=RH(r); | |
90 RH(r)=0; | |
91 end | |
92 end | |
93 | |
94 % While the column l is labelled, i.e. in path. | |
95 while (LC(l)~=0) | |
96 % If row r is explored.. | |
97 if (RH(r)==0) | |
98 % If all rows are explored.. | |
99 if (RH(n+1)<=0) | |
100 % Reduce cost matrix. | |
101 [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR); | |
102 end | |
103 | |
104 % Re-start with first unexplored row. | |
105 r=RH(n+1); | |
106 end | |
107 | |
108 % Get column of next free zero in row r. | |
109 l=CH(r); | |
110 | |
111 % Advance "column of next free zero". | |
112 CH(r)=-A(r,l); | |
113 | |
114 % If this zero is last in list.. | |
115 if(A(r,l)==0) | |
116 % ...remove row r from unexplored list. | |
117 RH(n+1)=RH(r); | |
118 RH(r)=0; | |
119 end | |
120 end | |
121 | |
122 % If the column found is unassigned.. | |
123 if (C(l)==0) | |
124 % Flip all zeros along the path in LR,LC. | |
125 [A,C,U]=hmflip(A,C,LC,LR,U,l,r); | |
126 % ...and exit to continue with next unassigned row. | |
127 break; | |
128 else | |
129 % ...else add zero to path. | |
130 | |
131 % Label column l with row r. | |
132 LC(l)=r; | |
133 | |
134 % Add l to the set of labelled columns. | |
135 SLC=[SLC l]; | |
136 | |
137 % Continue with the row assigned to column l. | |
138 r=C(l); | |
139 | |
140 % Label row r with column l. | |
141 LR(r)=l; | |
142 | |
143 % Add r to the set of labelled rows. | |
144 SLR=[SLR r]; | |
145 end | |
146 end | |
147 end | |
148 | |
149 % Calculate the total cost. | |
150 T=sum(orig(logical(sparse(C,1:size(orig,2),1)))); | |
151 | |
152 | |
153 function A=hminired(A) | |
154 %HMINIRED Initial reduction of cost matrix for the Hungarian method. | |
155 % | |
156 %B=assredin(A) | |
157 %A - the unreduced cost matris. | |
158 %B - the reduced cost matrix with linked zeros in each row. | |
159 | |
160 % v1.0 96-06-13. Niclas Borlin, niclas@cs.umu.se. | |
161 | |
162 [m,n]=size(A); | |
163 | |
164 % Subtract column-minimum values from each column. | |
165 colMin=min(A); | |
166 A=A-colMin(ones(n,1),:); | |
167 | |
168 % Subtract row-minimum values from each row. | |
169 rowMin=min(A')'; | |
170 A=A-rowMin(:,ones(1,n)); | |
171 | |
172 % Get positions of all zeros. | |
173 [i,j]=find(A==0); | |
174 | |
175 % Extend A to give room for row zero list header column. | |
176 A(1,n+1)=0; | |
177 for k=1:n | |
178 % Get all column in this row. | |
179 cols=j(k==i)'; | |
180 % Insert pointers in matrix. | |
181 A(k,[n+1 cols])=[-cols 0]; | |
182 end | |
183 | |
184 | |
185 function [A,C,U]=hminiass(A) | |
186 %HMINIASS Initial assignment of the Hungarian method. | |
187 % | |
188 %[B,C,U]=hminiass(A) | |
189 %A - the reduced cost matrix. | |
190 %B - the reduced cost matrix, with assigned zeros removed from lists. | |
191 %C - a vector. C(J)=I means row I is assigned to column J, | |
192 % i.e. there is an assigned zero in position I,J. | |
193 %U - a vector with a linked list of unassigned rows. | |
194 | |
195 % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. | |
196 | |
197 [n,np1]=size(A); | |
198 | |
199 % Initalize return vectors. | |
200 C=zeros(1,n); | |
201 U=zeros(1,n+1); | |
202 | |
203 % Initialize last/next zero "pointers". | |
204 LZ=zeros(1,n); | |
205 NZ=zeros(1,n); | |
206 | |
207 for i=1:n | |
208 % Set j to first unassigned zero in row i. | |
209 lj=n+1; | |
210 j=-A(i,lj); | |
211 | |
212 % Repeat until we have no more zeros (j==0) or we find a zero | |
213 % in an unassigned column (c(j)==0). | |
214 | |
215 while (C(j)~=0) | |
216 % Advance lj and j in zero list. | |
217 lj=j; | |
218 j=-A(i,lj); | |
219 | |
220 % Stop if we hit end of list. | |
221 if (j==0) | |
222 break; | |
223 end | |
224 end | |
225 | |
226 if (j~=0) | |
227 % We found a zero in an unassigned column. | |
228 | |
229 % Assign row i to column j. | |
230 C(j)=i; | |
231 | |
232 % Remove A(i,j) from unassigned zero list. | |
233 A(i,lj)=A(i,j); | |
234 | |
235 % Update next/last unassigned zero pointers. | |
236 NZ(i)=-A(i,j); | |
237 LZ(i)=lj; | |
238 | |
239 % Indicate A(i,j) is an assigned zero. | |
240 A(i,j)=0; | |
241 else | |
242 % We found no zero in an unassigned column. | |
243 | |
244 % Check all zeros in this row. | |
245 | |
246 lj=n+1; | |
247 j=-A(i,lj); | |
248 | |
249 % Check all zeros in this row for a suitable zero in another row. | |
250 while (j~=0) | |
251 % Check the in the row assigned to this column. | |
252 r=C(j); | |
253 | |
254 % Pick up last/next pointers. | |
255 lm=LZ(r); | |
256 m=NZ(r); | |
257 | |
258 % Check all unchecked zeros in free list of this row. | |
259 while (m~=0) | |
260 % Stop if we find an unassigned column. | |
261 if (C(m)==0) | |
262 break; | |
263 end | |
264 | |
265 % Advance one step in list. | |
266 lm=m; | |
267 m=-A(r,lm); | |
268 end | |
269 | |
270 if (m==0) | |
271 % We failed on row r. Continue with next zero on row i. | |
272 lj=j; | |
273 j=-A(i,lj); | |
274 else | |
275 % We found a zero in an unassigned column. | |
276 | |
277 % Replace zero at (r,m) in unassigned list with zero at (r,j) | |
278 A(r,lm)=-j; | |
279 A(r,j)=A(r,m); | |
280 | |
281 % Update last/next pointers in row r. | |
282 NZ(r)=-A(r,m); | |
283 LZ(r)=j; | |
284 | |
285 % Mark A(r,m) as an assigned zero in the matrix . . . | |
286 A(r,m)=0; | |
287 | |
288 % ...and in the assignment vector. | |
289 C(m)=r; | |
290 | |
291 % Remove A(i,j) from unassigned list. | |
292 A(i,lj)=A(i,j); | |
293 | |
294 % Update last/next pointers in row r. | |
295 NZ(i)=-A(i,j); | |
296 LZ(i)=lj; | |
297 | |
298 % Mark A(r,m) as an assigned zero in the matrix . . . | |
299 A(i,j)=0; | |
300 | |
301 % ...and in the assignment vector. | |
302 C(j)=i; | |
303 | |
304 % Stop search. | |
305 break; | |
306 end | |
307 end | |
308 end | |
309 end | |
310 | |
311 % Create vector with list of unassigned rows. | |
312 | |
313 % Mark all rows have assignment. | |
314 r=zeros(1,n); | |
315 rows=C(C~=0); | |
316 r(rows)=rows; | |
317 empty=find(r==0); | |
318 | |
319 % Create vector with linked list of unassigned rows. | |
320 U=zeros(1,n+1); | |
321 U([n+1 empty])=[empty 0]; | |
322 | |
323 | |
324 function [A,C,U]=hmflip(A,C,LC,LR,U,l,r) | |
325 %HMFLIP Flip assignment state of all zeros along a path. | |
326 % | |
327 %[A,C,U]=hmflip(A,C,LC,LR,U,l,r) | |
328 %Input: | |
329 %A - the cost matrix. | |
330 %C - the assignment vector. | |
331 %LC - the column label vector. | |
332 %LR - the row label vector. | |
333 %U - the | |
334 %r,l - position of last zero in path. | |
335 %Output: | |
336 %A - updated cost matrix. | |
337 %C - updated assignment vector. | |
338 %U - updated unassigned row list vector. | |
339 | |
340 % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. | |
341 | |
342 n=size(A,1); | |
343 | |
344 while (1) | |
345 % Move assignment in column l to row r. | |
346 C(l)=r; | |
347 | |
348 % Find zero to be removed from zero list.. | |
349 | |
350 % Find zero before this. | |
351 m=find(A(r,:)==-l); | |
352 | |
353 % Link past this zero. | |
354 A(r,m)=A(r,l); | |
355 | |
356 A(r,l)=0; | |
357 | |
358 % If this was the first zero of the path.. | |
359 if (LR(r)<0) | |
360 ...remove row from unassigned row list and return. | |
361 U(n+1)=U(r); | |
362 U(r)=0; | |
363 return; | |
364 else | |
365 | |
366 % Move back in this row along the path and get column of next zero. | |
367 l=LR(r); | |
368 | |
369 % Insert zero at (r,l) first in zero list. | |
370 A(r,l)=A(r,n+1); | |
371 A(r,n+1)=-l; | |
372 | |
373 % Continue back along the column to get row of next zero in path. | |
374 r=LC(l); | |
375 end | |
376 end | |
377 | |
378 | |
379 function [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR) | |
380 %HMREDUCE Reduce parts of cost matrix in the Hungerian method. | |
381 % | |
382 %[A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR) | |
383 %Input: | |
384 %A - Cost matrix. | |
385 %CH - vector of column of 'next zeros' in each row. | |
386 %RH - vector with list of unexplored rows. | |
387 %LC - column labels. | |
388 %RC - row labels. | |
389 %SLC - set of column labels. | |
390 %SLR - set of row labels. | |
391 % | |
392 %Output: | |
393 %A - Reduced cost matrix. | |
394 %CH - Updated vector of 'next zeros' in each row. | |
395 %RH - Updated vector of unexplored rows. | |
396 | |
397 % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. | |
398 | |
399 n=size(A,1); | |
400 | |
401 % Find which rows are covered, i.e. unlabelled. | |
402 coveredRows=LR==0; | |
403 | |
404 % Find which columns are covered, i.e. labelled. | |
405 coveredCols=LC~=0; | |
406 | |
407 r=find(~coveredRows); | |
408 c=find(~coveredCols); | |
409 | |
410 % Get minimum of uncovered elements. | |
411 m=min(min(A(r,c))); | |
412 | |
413 % Subtract minimum from all uncovered elements. | |
414 A(r,c)=A(r,c)-m; | |
415 | |
416 % Check all uncovered columns.. | |
417 for j=c | |
418 % ...and uncovered rows in path order.. | |
419 for i=SLR | |
420 % If this is a (new) zero.. | |
421 if (A(i,j)==0) | |
422 % If the row is not in unexplored list.. | |
423 if (RH(i)==0) | |
424 % ...insert it first in unexplored list. | |
425 RH(i)=RH(n+1); | |
426 RH(n+1)=i; | |
427 % Mark this zero as "next free" in this row. | |
428 CH(i)=j; | |
429 end | |
430 % Find last unassigned zero on row I. | |
431 row=A(i,:); | |
432 colsInList=-row(row<0); | |
433 if (length(colsInList)==0) | |
434 % No zeros in the list. | |
435 l=n+1; | |
436 else | |
437 l=colsInList(row(colsInList)==0); | |
438 end | |
439 % Append this zero to end of list. | |
440 A(i,l)=-j; | |
441 end | |
442 end | |
443 end | |
444 | |
445 % Add minimum to all doubly covered elements. | |
446 r=find(coveredRows); | |
447 c=find(coveredCols); | |
448 | |
449 % Take care of the zeros we will remove. | |
450 [i,j]=find(A(r,c)<=0); | |
451 | |
452 i=r(i); | |
453 j=c(j); | |
454 | |
455 for k=1:length(i) | |
456 % Find zero before this in this row. | |
457 lj=find(A(i(k),:)==-j(k)); | |
458 % Link past it. | |
459 A(i(k),lj)=A(i(k),j(k)); | |
460 % Mark it as assigned. | |
461 A(i(k),j(k))=0; | |
462 end | |
463 | |
464 A(r,c)=A(r,c)+m; |