由于之前忙着考研和毕业的事情,一直没有对DA算法进行一对一或者一对多的拓展,现在稍微有了一点富余的时间,打算把这一部分内容给做出来。
我自己的理解是,如果两个偏好矩阵都是mxm的正方形矩阵,即需要匹配的两个对象集的对象个数都相等,在这种情况下只需进行一对一的匹配,因为这种匹配关系这时是最稳定的。只有当两个对象集的对象个数不等的时候需要进行一对多或者多对一的匹配。关于这一部分,如果有不同想法的同好,欢迎与我交流。
整个代码的思路就是在(一)的基础上加了一个外循环,即内部依然是一对一的匹配,再一次匹配后,将已经获得匹配的对象剔除,再进行下一次循环匹配,直到所有匹配完成。这一步在代码中的处理就是令已经匹配对象的偏好度为零。
下面总的算法的代码
function [pairing_vec,conv_vec,time,sta]=DAalgs(PL_matr1,PL_matr2)
%完成延迟接受算法的一对多或者多对一匹配
%此种情况更适合于男女数不对等的情况下,为多余的男(女)进行匹配
%time--叠代次数;sta--稳定性
[m1,n1] = size(PL_matr1);%woman
[m2,n2] = size(PL_matr2);%man
pairing_vec = zeros(m1,m2);%初始化配对结果
number_min = min(m1,m2);%求两个列表中的较小值,求人数少的一方
number_max = max(m1,m2);%求两个列表中的较大值
man_reject = ones(1,m2);%标记man被拒绝
man_rejection_list = zeros(m2,n2);%清空man的拒绝列表
woman_proposal_list = zeros(m1,n1);%清空woman的可选列表
con_vec = zeros(m1,m2);
num = 1;
while( number_max > nozero(pairing_vec) )%人数多的一方的数目不等于配对矩阵中的非零数目时进行循环配对
for i = 1:m1
for j = 1:m2
if(pairing_vec(i,j))
if m1>m2
%man_rejection_list(i,j) = 1;
PL_matr1(i,:) = 0;
PL_matr2(:,i) = 0;
else
%man_rejection_list(i,j) = 1;
PL_matr1(:,j) = 0;
PL_matr2(j,:) = 0;
end
end
end
end
pairing_vec = zeros(m1,m2);%初始化配对结果
man_reject = ones(1,m2);%标记man被拒绝
man_rejection_list = zeros(m2,n2);%清空man的拒绝列表
woman_proposal_list = zeros(m1,n1);%清空woman的可选列表
while( number_min > nozero(pairing_vec) )%人数少的一方的数目不等于配对矩阵中的非零数目时进行循环配对
%index1 = 0;index2 = 0;
for i = 1:m2
mark_reject = man_reject(1,i);
index1 = 0;%index2 = 0;
if (mark_reject == 1) %&&(man_flag(1,i) == 0)) %如果mani被拒绝
for j = 1:m1
if (man_rejection_list(i,j) == 0) %&& (PL_matr2(i,j) > 0)%如果womanj未拒绝mani
index = PL_matr2(i,j); % 统计mani对womanj的喜欢程度
if index > index1
index1 = index;
%index2 = j;
end
man_reject(1,i) = 0; %标记mani为未拒绝
%break;
end
end
for j = 1:m1
%if woman_flag(1,j) == 0
if (PL_matr2(i,j) == index1) %&& (PL_matr2(i,j) > 0)
woman_proposal_list(j,i) = 1;%找到对mani喜欢程度最大的womanj,并将mani加入womanj的可选列
%man_reject(1,i) = 0; %标记mani为未拒绝
%break;
else
continue;
end
%end
end
else
continue;
end
end %生成woman_proposal_list
%index1 = 0;index2 = 0;
for j = 1:m1
woman_proposal = sum(woman_proposal_list(j,:));
index1 = 0 ;%index2 = 0 ;
if (woman_proposal ~= 0) %&& (PL_matr1(j,i) > 0)%&&(woman_flag(1,j) == 0)) %如果woman的可选列表大于0,即有可选对象
for i = 1:m2
%if man_flag(1,i) == 0
if (woman_proposal_list(j,i) == 1)
index = PL_matr1(j,i); % 统计mani对womanj的喜欢程度
if (index > index1) %&& (man_flag(1,i) == 0))
index1 = index;
%index2 = i;
end %找到对womanj喜欢程度最大的mani
end
%end
end
for i = 1:m2
%if man_flag(1,i) == 0
if (woman_proposal_list(j,i) == 1) %&& (PL_matr1(j,i) > 0)
if (PL_matr1(j,i) ~= index1)%将对womanj除了喜欢程度最大的man之外的所有man进行移除
woman_proposal_list(j,i) = 0; %从选择列表中移除
man_reject(1,i) = 1;%标记为被拒绝
man_rejection_list(i,j) = 1;%加入被拒绝列表
else
continue;
end
else
continue;
end
% else
% continue;
% end
end
else
continue;
end
woman_proposal = sum(woman_proposal_list(j,:));
index3 = 0;
index4 = 0;
if(woman_proposal > 1)%女生的可选列表不止有一个,但是此时只能保留一个
for i = 1:m2
if (woman_proposal_list(j,i) == 1)
index2 = PL_matr1(j,i);
if index2 > index3
index3 = index2 ;
index4 = i;
end
else
continue;
end
end
for i = 1:m2
if(i ~= index4)
woman_proposal_list(j,i) = 0; %从选择列表中移除
man_reject(1,i) = 1;%标记为被拒绝
man_rejection_list(i,j) = 1;%加入被拒绝列表
end
end
end
end %保证woman_proposal_list每一行只有一个1
pairing_vec = woman_proposal_list;%%进行配对
conv_vec = pairing_vec;
num = num+1;
end
con_vec = con_vec+pairing_vec;
number_min = min(number_min,number_max - nozero(con_vec));
pairing_vec = con_vec;
end
time = num;
sta1 = 0;
sta2 = 0;
for i = 1:m1
for j = 1:m2
if (woman_proposal_list(i,j) == 1)
sta1 = sta1+woman_proposal_list(i,j)*PL_matr1(i,j);
end
end
end
for i = 1:m1
for j = 1:m2
if (woman_proposal_list(i,j) == 1)
sta2 = sta2+woman_proposal_list(i,j)*PL_matr2(j,i);
end
end
end
sta = sta1 + sta2;
function result=nozero(A) %求矩阵中非零个数的函数
B = (A~=0);
result=sum(B(:));
end
end
欢迎各位与我私信交流,如有错误,请指正。