Making a Class Schedule Using a Genetic Algorithm 中的fitness函数的解析

genetic algotithm 排课

排课过程中的一些硬条件:

  • A class can be placed only in a spare classroom
  • No professor or student group can have more then one class at a time.
  • A classroom must have enough seats to accommodate all students.
  • To place a class in a classroom, the classroom must have laboratory equipment (computers, in our case) if the class requires it。

Fitness函数积分规则:

  • Each class can have 0 to 5 points
  • If a class uses a spare classroom, we increment its score.
  • If a class requires computers and it is located in the classroom with them, or it doesn't require them, we increment the score of the class.
  • If a class is located in a classroom with enough available seats, guess what, we increment its score.
  • If a professor has no other classes at the time, we increment the class's score once again.
  • The last thing that we check is if any of the student groups that attend the class has any other class at the same time, and if they don't, we increment the score of the class.
  • If a class breaks a rule at any time-space slot that it occupies, its score is not incremented for that rule.
  • The total score of a class schedule is the sum of points of all classes.
  • The fitness value is calculated as schedule_score/maximum_score, and maximum_score is number_of_classes*5.

这之间的联系可以这样:


这些限制条件关联了不同的对象,有课程对教室的要求,有学生或教授对课程的要求,有课程对课程表的要求(时间唯一性)。现在有个问题,有了这些限制条件,问题的解空间该怎么定义?怎么初始化一个初代的课程表?这分为两个步骤,一个是课程已经安排好了(一个课程指的是,确定好了上什么课,哪个老师上,哪些班级的学生去上,教室选在哪里),这时候上课的时间是不定的,也就是只有时间安排这一个变量,这时候把安排好的课程输入排课系统里进行优化排序。怎么安排课程呢?也就是统筹学生,老师,地点这些信息。上面这种思考方式有点偏离问题,教室和一周的时间都是可配置资源,应该是一起安排的,并不是先安排教室,然后在安排时间。

按照上面的资源分配来看,教师也可以看做一种分配资源,不过因为教师一般只教授一门课或者两门课,变化比较小,所以很多课表设计时,把这个部分是定死了。问题有点远了,后续在思考这部分问题,先解析下C++中的fitness源码。

Fitness源码部分c++

// Calculates fitness value of chromosome
void Schedule::CalculateFitness()
{
	// chromosome's score
	int score = 0;

	int numberOfRooms = Configuration::GetInstance().GetNumberOfRooms();
	int daySize = DAY_HOURS * numberOfRooms;

	int ci = 0;

	// check criterias and calculate scores for each class in schedule
	for( hash_map<CourseClass*, int>::const_iterator it = _classes.begin(); it != _classes.end(); ++it, ci += 5 )
	{
		// coordinate of time-space slot
		int p = ( *it ).second;
		int day = p / daySize;
		int time = p % daySize;
		int room = time / DAY_HOURS;
		time = time % DAY_HOURS;

		int dur = ( *it ).first->GetDuration();

		// check for room overlapping of classes
		bool ro = false;
		for( int i = dur - 1; i >= 0; i-- )
		{
			if( _slots[ p + i ].size() > 1 )
			{
				ro = true;
				break;
			}
		}

		// on room overlaping
		if( !ro )
			score++;

		_criteria[ ci + 0 ] = !ro;

		CourseClass* cc = ( *it ).first;
		Room* r = Configuration::GetInstance().GetRoomById( room );
		// does current room have enough seats
		_criteria[ ci + 1 ] = r->GetNumberOfSeats() >= cc->GetNumberOfSeats();
		if( _criteria[ ci + 1 ] )
			score++;

		// does current room have computers if they are required
		_criteria[ ci + 2 ] = !cc->IsLabRequired() || ( cc->IsLabRequired() && r->IsLab() );
		if( _criteria[ ci + 2 ] )
			score++;

		bool po = false, go = false;
		// check overlapping of classes for professors and student groups
		for( int i = numberOfRooms, t = day * daySize + time; i > 0; i--, t += DAY_HOURS )
		{
			// for each hour of class
			for( int i = dur - 1; i >= 0; i-- )
			{
				// check for overlapping with other classes at same time
				const list<CourseClass*>& cl = _slots[ t + i ];
				for( list<CourseClass*>::const_iterator it = cl.begin(); it != cl.end(); it++ )
				{
					if( cc != *it )
					{
						// professor overlaps?
						if( !po && cc->ProfessorOverlaps( **it ) )
							po = true;

						// student group overlaps?
						if( !go && cc->GroupsOverlap( **it ) )
							go = true;

						// both type of overlapping? no need to check more
						if( po && go )
							goto total_overlap;
					}
				}
			}
		}

total_overlap:

		// professors have no overlaping classes?
		if( !po )
			score++;
		_criteria[ ci + 3 ] = !po;

		// student groups has no overlaping classes?
		if( !go )
			score++;
		_criteria[ ci + 4 ] = !go;
	}

	// calculate fitess value based on score
	_fitness = (float)score / ( Configuration::GetInstance().GetNumberOfCourseClasses() * DAYS_NUM );
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值