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 );
}


猜你喜欢

转载自blog.csdn.net/tortelee/article/details/79314899