|go ahead... be a heretic|
Note: I started writing this before you posted your followup w/ code. It seems like you have a decent handle on a lot of this so far...
it seems like nearly any crossover is going to generate a schedule that immediately gets stillborn as an impossible deal.Then don't make impossible/infeasible schedules "stillborn." Chances are you will start out with a population of impossible course schedules anyway. So if your fitness function just checks whether the schedule is feasible or not (and gives any non-feasible schedule zero fitness), you are just waiting for mutations to take you into the realm of valid schedules. That's even worse than a brute-force solution.
Your fitness function should have a good gradient over the entire search space. Some impossible schedules are more impossible than others. Take off X points for each instructor conflict, Y points for each room conflict, etc. You'll get continually closer to a valid schedule.
As for satisfying the students' course ranking, I would have each student give a satisfaction rating to each schedule. 1 point for each of his/her top 5 choices that he/she can attend (i.e, that are scheduled and don't overlap). Then take the average over all the students and add that to the fitness for the schedule (this will be an expensive fitness function to compute). Obviously weight the big room/teacher conflicts more than the student preferences (which it seems you have already done).
As for representation, my preference would be a function mapping classroom timeslots to courses (i.e, an array: course assignmed to 1st slot, course assignmed to 2nd slot, etc). This way you are always sure that all the classroom slots are filled. Then you just take off points for classes scheduled twice, or teachers with two slots at the same time. Crossover is a snap now, as you can have different population members specialize in a good schedule for the beginning/end of the week and combine them to get a really good full-week schedule.
but if someone has a better module, I'll use that instead.I mentioned in the CB that I have written Algorithm::Evolve. You can be the judge of whether it's better (I have never looked at AI::Genetic) -- and I'm always open to suggestions. Check out the distribution's examples/ dir.