【圖】二分圖最大匹配算法的應用及Matlab實現


  專業課程設計的作業,當初花了差不多三個晚上最后終於實現了Edmonds算法並解決該問題,最后還學會了用Matlab做簡單的交互界面,算是到目前為止本人自我感覺寫得最成功的程序,以防將來再重裝系統導致文件丟失,所以發上來,歡迎大家發郵件交流指正交流.

  如果對於二分圖最大匹配算法不熟悉,可以參考前篇博文:http://www.cnblogs.com/visayafan/archive/2012/05/12/2496896.html


View more documents from visayafan

 

一共有RecuCal.m LockMap.m BuildMatrix.m Edmonds.m GUI1.m 這幾個文件,我把它們合到一塊粘上去了,你再把他們分開保存就可以了. 
其中前三個文件都是為建立鄰接矩陣服務的,Edmonds.m是匈牙利算法的主文件,GUI1.m只是調用Edmonds.m做個界面而已。 
調用關系是GUI1.m調用Edmonds.m; Edmonds.m調用BuildMatrix.m和LockMap.m ;LockMap.m調用RecuCal.m 
最后運行GUI1.m就ok了 

#LockMap.m
function [LMA, LMB] = LockMap(n, m)
% LOCKMAP - 求解滿足條件鎖並設置相應的映射
% 輸入參數:n 表槽數,m 表高度數。
% 輸出參數:LMA,LMB 分別為二維矩陣表示自然數到滿足條件鎖之間的映射。
global jiA ouB ary A B mm N
N = n; mm = m;
jiA=0; ouB=0;
A=[]; B=[];
ary = zeros(1, n);
RecuCal(n);
LMA=A; LMB=B;
[lena, n] = size(LMA);
[lenb, n] =size(LMB);
if lena>lenb
    temp = LMA; LMA=LMB;LMB=temp;
    temp = lena;lena=lenb;lenb=temp;
end



#RecuCal.m
function RecuCal(n)
% RECUCAL - 遞歸函數
global jiA ouB ary A B mm N
if n ==1
    for k=1:mm
        % 調用遞歸函數時要用到的變量所以
        % 設為全局
        ary(1) = k;
        Max = max(ary); Min = min(ary);
        num = 0; neighbor = 0;
        for i=1:N
            num = num + (Max-ary(i))*(ary(i)-Min);
            if (i~=N)
                neighbor = max(neighbor, abs(ary(i)-ary(i+1)));
            end
        end
        if (neighbor > mm-1.5)&&(num > 0.5)
            if mod(sum(ary), 2)
                % 奇數,屬於 A 類
                jiA = jiA+1;
                A(jiA,:) = ary;
            else
                % 偶數,屬於 B 類
                ouB = ouB+1;
                B(ouB,:) = ary;
            end
        end
    end
else
    for k=1:mm
        ary(n) = k;
        RecuCal(n-1);
    end
end



#BuildMatrix.m
function AB = BuildMatrix(LMA, LMB)
% BUILDMATRIX - 建立鄰接矩陣,若 i 與 j 之間可以互開則 AB(i,j)=1,否則為 0。
AB = [];
[lena, n] = size(LMA);
[lenb, n] =size(LMB);
for i = 1:lena
    for j=1:lenb
        tmp = 0;
        for k=1:n
            tmp = tmp + abs(LMA(i,k)-LMB(j,k));
        end
        if tmp == 1
            AB(i, j)=1;
        end
    end
end





#Edmonds.m
function str = Edmonds(n, m)
% EDMONDS - Edmonds 算法尋找完美匹配
str = [];
[LMA, LMB] = LockMap(n, m);
AB = BuildMatrix(LMA, LMB);
lena = length(LMA);
lenb = length(LMB);
if lena==0
    disp('其中一個分組為空,
    無法匹配'); %當 n=m=3 時只有偶數組無奇數組,
    不能完成
    匹配
    return;
end
MatA = zeros(1, lena);
MatB = zeros(1, lenb);
X = MatA; Y=MatB; Z=Y;
NumNoMat = 0;
% 無法匹配的點的個數
% 最初匹配,只有一個匹配
j = find(AB(1,:), 1);
MatA(1)=j; MatB(j)=1;
while length(find(MatA==0)) ~= 0
    % 存在不匹配的元素
    J = find(MatA==0); i = J(1);
    % 第 i 個元素未被匹配
    init = i; X(i)=0;
    J = find(AB(i,:));
    % J 為所有與 i 相鄰結點
    Y(J) = i; j=J(1);
    while ~isempty(find(Y~=Z))
        if MatB(j) ~= 0
            % j 是匹配點
            Z(j) = Y(j);
            i = MatB(j);
            X(i)=j;
            J = find(AB(i,:));
            Y(J)=i;
            J = find(Y);
            JJ = find(Z);
            J = setxor(intersect(J, JJ), J);
            j=J(1);
        else
            % j 不是匹配點
            i = Y(j);
            MatA(i) = j;
            MatB(j) = i;
            while X(i)
                j = X(i);
                i = Z(j);
                MatA(i) = j;
                MatB(j) = i;
            end
            break;
        end
    end
    % 如果 Y==Z 則表明該點沒有與之相應的匹配,即不存在完美匹配,在 MatA 中標
    % 記為-1if isempty(find(Y~=Z, 1))
        NumNoMat = NumNoMat + 1;
        MatA(init) = -1;
    end
    X(1:lena)=0; Y(1:lenb)=0; Z=Y;
end
total = 0;
for i=1:lena
    k = MatA(i);
    if k<=0 continue; end
    % k<=0 時表明匹配不存在
    stra = ''; strb = '';
    for j=1:n
        stra = [stra, num2str(LMA(i, j)), ' '];
        strb = [strb, num2str(LMB(k, j)), ' '];
    end
    str = [str, stra, '------ ', strb, 10];
    total = total + 1;
end
str = [str, '匹配個數有:', num2str(total)];



#GUI1.m
function varargout = GUI1(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',
mfilename, ...
    'gui_Singleton', gui_Singleton, ...
    'gui_OpeningFcn', @GUI1_OpeningFcn, ...
    'gui_OutputFcn', @GUI1_OutputFcn, ...
    'gui_LayoutFcn', [] , ...
    'gui_Callback', []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before GUI1 is made visible.
function GUI1_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = GUI1_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
function pushbutton1_Callback(hObject, eventdata, handles)
a = get(handles.edit1, 'String');
b = get(handles.edit2, 'String');
str = Edmonds(str2num(a), str2num(b));
set(handles.edit4, 'String', str);
guidata(hObject, handles);
function edit1_Callback(hObject, eventdata, handles)
input = str2num(get(hObject, 'String'));
guidata(hObject, handles);
function edit1_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'),
    get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function edit2_Callback(hObject, eventdata, handles)
input = str2num(get(hObject, 'String'));
guidata(hObject, handles);
function edit2_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'),
    get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function slider1_Callback(hObject, eventdata, handles)
function slider1_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'),
    get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end
function text_result_Callback(hObject, eventdata, handles)
function text_result_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'),
    get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function edit4_Callback(hObject, eventdata, handles)
function edit4_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'),
    get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function pushbutton2_Callback(hObject, eventdata, handles)
set(handles.edit4, 'String', '');
set(handles.edit1, 'String', '');
set(handles.edit2, 'String', '');

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM