#基于遗传算法的matlab自动排班程序
该代码生成排14个人每周值班一次的值班表。先统计14个人每周的无课情况,如图所示:
如:第二行第二列的“245”表示该同学第一节课的周二周四周五没课。
将14个同学进行编号处理,如:陈郭涛为1,潘荣为2,张加斌为3。
然后通过下列代码:
%%初始化
clc;
clear;
c=14;%值班人数
[NUM,TXT,RAW]=xlsread('wukebiao','B9:O12');
w=cell(1,c);
%%
%生成所有人这周的课表
for i=1:c
w{1,i}=ones(4,5);
end
for j=1:c
wk=w{1,j};
x=zeros(4,5);
for i=1:4
z=num2str(RAW{i,j});
for k=1:size(z,2)
x(i,k)=str2num(z(k));
end
for m=1:size(x,1)
for n=1:size(x,2)
if x(m,n)~=0
wk(m,x(m,n))=0;
end
end
end
end
w{1,j}=wk;
end
%%
%遗传算法初始化
m=10;%种群数目
zb=zeros(4,5);%值班表
p=cell(1,m);%初始化种群
for i=1:m
p{1,i}=randperm(20,14);%个体初始化
end
%%
pan=0;
zhiban=zeros(4,5);
%判断适应度是否等于1
while(1)
%计算初始时种群的所有适应度
for i=1:m
h=p{1,i};
y=judgment(w,h);
b(i)=y;
end
%判断适应度是否等于1
for i=1:m
if b(i)==1
pan=1;
disp('****值班表****')
zhi=p{1,i};
for i=1:14
zhiban(zhi(i))=i;
end
disp(zhiban);
break;
end
end
if pan==1
break;
end
l=select(b,m,p);%选择
v=cross1(l,m,b,w);%交叉
%变异
for i=1:m
r=variation(v{1,i},m);
v{1,i}=r;
end
p=v;
end
xlswrite('zhibanbiao',zhiban,'B3:F6');
%%
%建立适应度函数
function y=judgment(w,h)
y=0;
for i=1:14
s=w{1,i}; %将值班人的课表导入s
if s(h(i))==0 %判断该值班人在上述值班中是否有课
y=y+1; %无课,y++
end
end
y=y/14;%适应度
end
%%
%应用轮盘选择
function l=select(b,m,p)
%b 为所有适应度的矩阵
%m 为种群的数目
%p 为种群的所有染色体矩阵
l=cell(1,10);
for i=1:m
B(i)=b(i)/sum(b);%选中某个体的概率
end
C=[0 cumsum(B)];%确定转盘
%选择优质的染色体
for i=1:m
y=rand(1);
for j=1:m
if y>C(j)&&y<=C(j+1)
l{1,i}=p{1,j};%选中的染色体
end
end
end
end
%%
%交叉函数
function one=cross(x,y,m,w)
one1=x;
two1=y;
p=0;
for i=1:14 %取出x中有课的人的编号
s=w{1,i};
if s(x(i))==1
p=p+1;
k(p)=i;
end
end
for i=1:length(k) %将x中有课的人与y交叉
t=x(k(i));
x(k(i))=y(k(i));
y(k(i))=t;
end
one=x;
two=y;
%判断交叉后的染色体是否有重复的基因,若重复,不交叉
for i=1:m-1
q=0;
for j=1:m
if x(i)==x(j)
q=1;
one=one1;
two=two1;break;
end
end
if q==1
break;
end
end
end
%%
%对染色体进行交叉,交叉率为100%
function v=cross1(l,m,b,w)
%l为选中的所有染色体矩阵
%m为种群的数目
[ones iz]=max(b);%取出最大的适应度的个体
for i=1:m
one=cross(l{1,iz},l{1,i},m,w);
v{1,i}=one;
end
end
%%
%变异,其变异率为0.09:从一个染色体中随机选一个基因,将该基因变异成该染色体没有的基因
function r=variation(u,m)
%u为一个染色体
if rand(1)<=0.09
y=randperm(14,1);
ks=0;
ut=[1:20];
%提取染色体中没有的基因
for i=1:14
for j=1:20-i
if u(i)==ut(j)
ut(j)=[];break;
end
end
end
u(y)=ut(randperm(4,1));
r=u;
else
r=u;
end
end
%%
运行得出:
****值班表****
0 12 3 14 1
0 0 8 4 10
5 13 0 2 0
6 7 11 9 0
每个编号对应着一个同学,其0代表着没人值班。
这就完成了自动排班的程序。