Daniel@0: % MATCH - Solves the weighted bipartite matching (or assignment) Daniel@0: % problem. Daniel@0: % Daniel@0: % Usage: a = match(C); Daniel@0: % Daniel@0: % Arguments: Daniel@0: % C - an m x n cost matrix; the sets are taken to be Daniel@0: % 1:m and 1:n; C(i, j) gives the cost of matching Daniel@0: % items i (of the first set) and j (of the second set) Daniel@0: % Daniel@0: % Returns: Daniel@0: % Daniel@0: % a - an m x 1 assignment vector, which gives the Daniel@0: % minimum cost assignment. a(i) is the index of Daniel@0: % the item of 1:n that was matched to item i of Daniel@0: % 1:m. If item i (of 1:m) was not matched to any Daniel@0: % item of 1:n, then a(i) is zero. Daniel@0: Daniel@0: % Copyright (C) 2002 Mark A. Paskin Daniel@0: % Daniel@0: % This program is free software; you can redistribute it and/or modify Daniel@0: % it under the terms of the GNU General Public License as published by Daniel@0: % the Free Software Foundation; either version 2 of the License, or Daniel@0: % (at your option) any later version. Daniel@0: % Daniel@0: % This program is distributed in the hope that it will be useful, but Daniel@0: % WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Daniel@0: % General Public License for more details. Daniel@0: % Daniel@0: % You should have received a copy of the GNU General Public License Daniel@0: % along with this program; if not, write to the Free Software Daniel@0: % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 Daniel@0: % USA. Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: function [a] = optimalMatching(C) Daniel@0: Daniel@0: % Trivial cases: Daniel@0: [p, q] = size(C); Daniel@0: if (p == 0) Daniel@0: a = []; Daniel@0: return; Daniel@0: elseif (q == 0) Daniel@0: a = zeros(p, 1); Daniel@0: return; Daniel@0: end Daniel@0: Daniel@0: Daniel@0: if 0 Daniel@0: % First, reduce the problem by making easy optimal matches. If two Daniel@0: % elements agree that they are the best match, then match them up. Daniel@0: [x, a] = min(C, [], 2); Daniel@0: [y, b] = min(C, [], 1); Daniel@0: u = find(1:p ~= b(a(:))); Daniel@0: a(u) = 0; Daniel@0: v = find(1:q ~= a(b(:))'); Daniel@0: C = C(u, v); Daniel@0: if (isempty(C)) return; end Daniel@0: end Daniel@0: Daniel@0: % Get the (new) size of the two sets, u and v. Daniel@0: [m, n] = size(C); Daniel@0: Daniel@0: %mx = realmax; Daniel@0: mx = 2*max(C(:)); Daniel@0: mn = -2*min(C(:)); Daniel@0: % Pad the affinity matrix to be square Daniel@0: if (m < n) Daniel@0: C = [C; mx * ones(n - m, n)]; Daniel@0: elseif (n < m) Daniel@0: C = [C, mx * ones(m, m - n)]; Daniel@0: end Daniel@0: Daniel@0: % Run the Hungarian method. First replace infinite values by the Daniel@0: % largest (or smallest) finite values. Daniel@0: C(find(isinf(C) & (C > 0))) = mx; Daniel@0: C(find(isinf(C) & (C < 0))) = mn; Daniel@0: %fprintf('running hungarian\n'); Daniel@0: [b, cost] = hungarian(C'); Daniel@0: Daniel@0: % Extract only the real assignments Daniel@0: ap = b(1:m)'; Daniel@0: ap(find(ap > n)) = 0; Daniel@0: Daniel@0: a = ap; Daniel@0: %% Incorporate this sub-assignment into the complete assignment Daniel@0: % k = find(ap); Daniel@0: % a(u(k)) = v(ap(k)); Daniel@0: