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;