https://github.com/chunxi-alpc/CoursesScheduleGA
-
问题描述
在排课问题中,我们的主要任务是将班级、教室、课程、教师安排在一周内且不发生时间冲突。据此,做出如下假设:
学校有5个班,13种课程,23名教师和5个教室。
●教室集合R(301-101,301-102,301-103,301-104,301-105),假设每间教室只可容纳一个班的人;
●班级集合C(1班,2班,3班,4班,5班)
●课程集合S(100002,100008,100017,100024,100026,100040,100041,100042,100043,100044,100045 ,100046,100047),每门课可由多名教师上课;
下图为每个班的培养方案。表格中的数字代表需要安排的课时,其中每天一课时。
●教师集合T(T1,T2…T23),每位教师可教授多门课,在初始设置时设定教师的排课要求,其中,表格中值为1表示此行序号的教师能够教授课程编号为此列序号的课程。
●时间段,假设一周七天都可以上课,一个学期有19周。
一张正确的课表应至少满足以下硬约束条件:
(1)一个教师在同一时间段内只能安排一门课程;
(2)一个班级在同一时间段内只能安排一门课程;
(3)一个课室在同一时间段内只能安排一个班上一门课程。
除了上述的硬性约束,还有些软约束,这些软约束有助于使得课表更加合理,更加人性化。这些软约束条件可能是:
(1)尽量在早上安排必修课,而下午安排选修课,晚上尽量不排课;
(2)尽可能满足个别教师的特殊上课时间要求;
(3)一门课尽量分散在一个星期中,即某天上完某一门课后,要隔一天以上再上这门课,以使教师有充足的时间备课和批改作业,而学生也有足够的时间复习消化;
(4)学生课表中的上课时间不能过分集中,应避免一天课程很满而另一天却一整天没课的情况;
(5)一门课程的教学任务应该分担给每位能教学这门课的教师。
这些软约束条件各院校有所不同,在我们的研究中,旨在我们定义的约束范围内给出一个遗传算法的解决方法,并对其进行优化操作。
-
遗传算法
遗传算法采用类似基因演化的循环过程,其演算过程如下:
- 针对待解决问题随机生成一组解,我们称之为种群(Population)。种群中的每个个体都是问题的解。
2)对个体适应度进行评估,如果个体的适应度符合优化准则,则输出最佳个体及其代表的最优解,并结束计算,否则转向第3步。
3)根据适应度对种群进行排序,从中挑选出最优的几个个体加入下一代种群,这一个过程也被称为精英选拔。新种群余下的部分通过对选拔出来的精英个体进行修改得到。
4)按照一定的交叉概率和交叉方法生成新的个体。交叉的做法是随机从最优种群中选取两个个体,以某个位置为交叉点合成一个新的个体。
5)按照一定的变异概率和变异方法生成新的个体。变异的做法是对种群做一个微小的、随机的改变。如果解的编码方式是二进制,那么就随机选取一个位置进行0和1的互相突变;如果解的编码方式是十进制,那么就随机选取一个位置进行随机加减。
6)由交叉和变异产生新一代的种群,然后返回第2步。如图所示。
以下是遗传算法的伪代码:
BEGIN:
I=0;
Initialize P(I);
Fitness P(I);
While(not Terminate-Condition)
{
I++;
GA-Operation P(I);
Fitness P(I);
}
END.
-
基于遗传算法的排课设计
1. 染色体编码
GA中首要考虑的是如何表现其问题,即如何对染色体编码,使之适用于GA操作。在经典的遗传算法中,常采用浮点数或二进制的编码方法,而研究中,每条染色体代表每一节课的安排,其结构表示如下:
首先定义一个课程类,这个类包含了课程、班级、教师、教室、星期、周次几个属性。课程、班级、教师是安排好了的,教室、星期、周次是通过搜索算法来安排。
每一条染色体表示一种可能的排课结果,至于排课结果的优劣,则由适应度函数评估染色体的适应值来决定。
2. 适应度函数
遗传算法在进化中是以每个个体的适应度值为依据来选取下一代种群的。适应度函数设定的好坏直接影响到遗传算法的收敛速度和能否找到最优解。在本系统中,适应度函数的设计思想是对每条染色体中存在的冲突类型进行加权求和,其中权值Wi代表的是第i条规则的重要程度,若某条染色体违反了某条规则i,则将其值Pi置为1(若没有违反规则i,则Pi值为0),其受到的惩罚值为Wi*Pi 。染色体适应度函数值越小,则表示其拥有较好的授课时段和教室,其在下一代的演化中的生存概率就较大。
在这次设计的适应性(schedule_cost)把Wi默认为1,具体如图所示:
这个函数用来计算课表种群的冲突。当被测试课表冲突为0的时候,这个课表就是个符合规定的课表。冲突检测遵循下面几条规则:
同一个教室在同一个时间只能有一门课。
同一个班级在同一个时间只能有一门课。
同一个教师在同一个时间只能有一门课。
3. 初始化种群
初始化的目的在于为后面的遗传操作提供初始种群。把所有的课程安排都放在一条染色体里。
4. 进化总框架
5. 交叉[Crossover]
交叉是根据选择操作的结果,选取两条染色体作为父个体,再取一随机值random与系统预设的交叉率值(mutprob)比较,若random<mutprob则进行交换基因。
6. 变异[Mutate]
变异是随机改变染色体中任一授课时段,将时段随机抽取一点在设定范围内改变。变异运算模仿了生物在自然遗传环境中由于各种偶然因素引起的基因突变,通过变异,染色体适应度有可能加强也有可能降低,但它确保了种群中遗传基因类型的多样性,使搜索能在尽可能大的空间中进行,获得最优解的可能性大大加强。
- 实验结果
输出文件“各班课程安排.xlsx”,打开后如图:
本系统用python实现上述遗传排课算法,并对自行假设的模拟数据(问题描述中有详细描述)作了测试。关于遗传算法的参数设定:染色体为32条,交变异率为0.3,精英个数为8,演化的代数最大值为500代。
从课表中可以看出该课表不存在教师、教室、班级冲突,条件得到满足。
四.总结
本文论述了利用遗传算法求解高校课表的安排问题,实验证明文中提出的染色体编码方案和适应度函数是可行的,适应度函数值能够随着进化代数的增加而呈不断上升趋势,实验结果令人满意。在染色体编码方案方面,今后还准备考虑更复杂的课程安排要求。
对于提高遗传算法收敛速度的方法的思考:
三个可行的改进方法:
1. 保持当前的一个最好解.它不参加变异和交叉操作.我们知道,遗传算法依靠再生保持优秀种群,依靠变异和交叉操作来达到改变搜索区间.以便不断得到最好解.变异和交叉操作是随机进行的,可能得到最好解,也可能破坏已经得到的最好解.当变异和交叉操作的概率大时,破坏的可能性也大.因此,在应用遗传算法时,人们不断调整这两个概率,以便即能扩大搜索区问,又能不破坏已经得到的最好解,但在简单遗传算法中,这是不可能的.而保持当前的一个最好解这个方法,就能达到即能扩大搜索区间,又能不破坏已经得到的最好解的目的.当变异和交叉操作的概率较大时,一定能扩大搜索区间.容易获得最好解.又因为当前的一个最好解不参加变异和交叉操作,所以不可能破坏它.在下一次变异时,所获得的解一定比当前的一个最好解更好时才能够保留它.故这个方法能够加快算法的搜索的速度并逼近最优解.在模拟实验中,还发现,该方法的变异概率的范围是0.1~0.3,而某些人推荐的变异概率的范围是0.001~0.0l.该方法不象简单遗传算法那样对变异概率的大小敏感,无论其变异概率的大小,只要在变异概率的范围内,都能很快地收敛。
2. 不断搜索新的解区间.在变异过程中,如果前后两次变异都发生在同一位时,人为地改变到其他位去.可以向低位变,也可以向高位变,这个根据需要改变.因为变异不同的位,搜索步长不同,每个分量的取值不同,搜索的解区间不同,这样更容易发现好的解和节约时间。
3. 改变种群的表示变量的串长.根据定理知,串的每个段的长度越长,位长的数学期望越大,变异搜索的步长也越大,搜索的范围也大,它的分辩能力好.但是,在最优解附近,变异搜索的步长大并不好,应当减少搜索的步长,以较快的速度逼近最优解.以免产生振荡.开始时,每个分量的串长最长,随着解的改善,不断减少串长,以减少搜索的步长和搜索的时间.