步骤1;减去每一行的最小值
步骤2:找到矩阵中的0值,如果其所在的行或列没有被标记的0,则用星号标记,对矩阵中的每个0元素进行此操作
步骤3:检查是否每一列都有一个被标记星号的0,如果每一列都被覆盖,则完成,否则进行步骤4
步骤4:找到一个没有被 覆盖的0并标记(加撇),如果包含此启动零的行中没有加星号的零,请转到步骤 5。否则,覆盖此行并显示包含加星号零的列。以这种方式继续,直到没有未覆盖的零。保存最小的未覆盖值,然后转到步骤 6。
步骤5:构造一系列交替的加撇零点和星号零点,设 Z0 表示在步骤 4 中找到的未覆盖的启动零点,设 Z1 表示 Z0 列中的星号零(如果有)。设 Z2 表示 Z1 行中的启动零(总有一个)。继续操作,直到序列在其列中没有星号零的启动零点处终止。 取消系列中0的星号,为该系列的每个加撇零号加星号,擦除所有加撇并揭开矩阵中的每一行。 返回步骤 3。
步骤6:将最小未覆盖值添加到每个覆盖行的每个元素,然后从每个未覆盖列的每个元素中减去该值。返回到步骤 4,而不更改任何星形、加撇或覆盖线。
function [assignment] = munkres(costMat)
% MUNKRES Munkres Assign Algorithm
%
% [ASSIGN,COST] = munkres(COSTMAT) returns the optimal assignment in ASSIGN
% with the minimum COST based on the assignment problem represented by the
% COSTMAT, where the (i,j)th element represents the cost to assign the jth
% job to the ith worker.
%
% This is vectorized implementation of the algorithm. It is the fastest
% among all Matlab implementations of the algorithm.
% Examples
% Example 1: a 5 x 5 example
%{
[assignment,cost] = munkres(magic(5));
[assignedrows,dum]=find(assignment);
disp(assignedrows’); % 3 2 1 5 4
disp(cost); %15
%}
% Example 2: 400 x 400 random data
%{
n=5;
A=rand(n);
tic
[a,b]=munkres(A);
toc
%}
% Reference:
% “Munkres’ Assignment Algorithm, Modified for Rectangular Matrices”,
% http://csclab.murraystate.edu/bob.pilgrim/445/munkres.html
% version 1.0 by Yi Cao at Cranfield University on 17th June 2008
assignment = false(size(costMat));
costMat(costMat~=costMat)=Inf;
validMat = costMat<Inf;
validCol = any(validMat,1);
validRow = any(validMat,2);
nRows = sum(validRow);
nCols = sum(validCol);
n = max(nRows,nCols);
if ~n
return
end
dMat = zeros(n);
dMat(1:nRows,1:nCols) = costMat(validRow,validCol);
%*************************************************
% Munkres’ Assignment Algorithm starts here
%*************************************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% STEP 1: Subtract the row minimum from each row.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dMat = bsxfun(@minus, dMat, min(dMat,[],2));
%**************************************************************************
% STEP 2: Find a zero of dMat. If there are no starred zeros in its
% column or row start the zero. Repeat for each zero
%**************************************************************************
zP = ~dMat; %选择0值
starZ = false(n); %初始星号矩阵
while any(zP(😃)
[r,c]=find(zP,1);
starZ(r,c)=true; %在星号矩阵中标记位置
zP(r,:)=false;
zP(:,c)=false;
end
while 1
%**************************************************************************
% STEP 3: Cover each column with a starred zero. If all the columns are
% covered then the matching is maximum
%**************************************************************************
primeZ = false(n);
coverColumn = any(starZ); %是否每一列都有一个0
if any(coverColumn)
break
end
coverRow = false(n,1); %如果不是 需要找到相应的行
while 1
%**************************************************************************
% STEP 4: Find a noncovered zero and prime it. If there is no starred
% zero in the row containing this primed zero, Go to Step 5.
% Otherwise, cover this row and uncover the column containing
% the starred zero. Continue in this manner until there are no
% uncovered zeros left. Save the smallest uncovered value and
% Go to Step 6.
%**************************************************************************
zP(😃 = false; %全0
zP(coverRow,coverColumn) = dMat(coverRow,~coverColumn); %将没有0的列标记处出来 0->1 1->0
Step = 6;
while any(any(zP(coverRow,coverColumn)))
[uZr,uZc] = find(zP,1); %依次找到没有0的行
primeZ(uZr,uZc) = true; %用初始化矩阵标记
stz = starZ(uZr,:); %在星号矩阵中 找到已经被覆盖的行
if ~any(stz) %如果行没有已经覆盖的0 step 5
Step = 5;
break;
end
coverRow(uZr) = true; %覆盖新找到的行
coverColumn(stz) = false; %揭开星号矩阵中已经被覆盖(有0)的行
zP(uZr,:) = false; % 在矩阵中将新覆盖的行去掉
zP(~coverRow,stz) = dMat(coverRow,stz); %在矩阵中重新显示已经被覆盖的列
end
if Step == 6
% *************************************************************************
% STEP 6: Add the minimum uncovered value to every element of each covered
% row, and subtract it from every element of each uncovered column.
% Return to Step 4 without altering any stars, primes, or covered lines.
%**************************************************************************
M=dMat(coverRow,coverColumn);
minval=min(min(M));
if minval==inf
return
end
dMat(coverRow,coverColumn)=dMat(coverRow,coverColumn)+minval;
dMat(coverRow,coverColumn)=M-minval;
else
break
end
end
%**************************************************************************
% STEP 5:
% Construct a series of alternating primed and starred zeros as
% follows:
% Let Z0 represent the uncovered primed zero found in Step 4.
% Let Z1 denote the starred zero in the column of Z0 (if any).
% Let Z2 denote the primed zero in the row of Z1 (there will always
% be one). Continue until the series terminates at a primed zero
% that has no starred zero in its column. Unstar each starred
% zero of the series, star each primed zero of the series, erase
% all primes and uncover every line in the matrix. Return to Step 3.
%**************************************************************************
rowZ1 = starZ(:,uZc); % 被覆盖的行没有0 找到相应的列
starZ(uZr,uZc)=true; %新找到的行列 覆盖
while any(rowZ1)
starZ(rowZ1,uZc)=false; %揭开之前的覆盖
uZc = primeZ(rowZ1,:);
uZr = rowZ1;
rowZ1 = starZ(:,uZc);
starZ(uZr,uZc)=true;
end
end
%生成标签矩阵
assignment(validRow,validCol) = starZ(1:nRows,1:nCols);
%解决标签映射问题不需要计算权重cost,故将其注释
%cost = 0;
%cost = sum(costMat(assignment));