private Slot GetNewSlot(CourseClass cc) { //TODO: 没有考虑午休 Slot newSlot = null; int count = 0; int group = this.configuration.GetStudentsGroupIdx(cc); bool isFixed = false; // 尽量选中空slot,最多尝试10次 do { // 第几个工作日 int day = this.Rand() % this.configuration.Parameters.WorkingDaysNumber; // 第几节课开始上,考虑了duration int time = this.Rand() % (this.configuration.Parameters.NumberOfClassPerDay + 1 - cc.Duration); // 如果用户有偏好,前5次尝试按照用户偏好优先。如果不能成功,则忽略偏好。 if (count < 5 && cc.ExpectedClassIndexes != null && cc.ExpectedClassIndexes.Length > 0) { if (cc.ExpectedClassIndexes.Length == 1) { time = cc.ExpectedClassIndexes[0]; } else { int idx = this.Rand() % cc.ExpectedClassIndexes.Length; time = cc.ExpectedClassIndexes[idx]; } } // 得到新的时间槽 newSlot = this.GetSlot(day, group, time); isFixed = false; bool isOccupied = false; for (int i = 0; i < cc.Duration; i++) { // 是否包含已经冻结的slot if (this.Slots[newSlot.SlotIndex + i].IsFixed) { isFixed = true; break; } // Slot是否为空,我们希望优先选中空slot if (this.Slots[newSlot.SlotIndex + i].Classes.Count > 0) { isOccupied = true; } } if (!isOccupied) { break; } }while (isFixed || count++ < 10); return(newSlot); }
/// <summary> /// 随机选择一个可排课的课堂 /// </summary> /// <returns>一个课堂</returns> private CourseClass GetRandomUnfixedClass() { CourseClass cc = null; do { cc = this.configuration.CourseClasses[this.Rand() % this.configuration.CourseClasses.Count]; }while (cc.IsFixed); return(cc); }
// Performs mutation on chromosome // 在当前染色体上执行变异 public void Mutation() { this.SelfCheck(); // 检查是否需要变异 if (this.Rand() % 100 > this.configuration.Parameters.MutationProbability) { return; } // move selected number of classes at random position // 随机移动指定数量课堂的时间槽 for (int i = this.configuration.Parameters.MutationSize; i > 0; i--) { // 随机选择一个课堂 CourseClass cc = this.GetRandomUnfixedClass(); // 将课堂从现在的时间槽里删除 foreach (var slot in this.GetSlots(cc)) { slot.Classes.Remove(cc); } // 随机决定课堂新的时间槽 int newSlotIndex = this.GetNewSlot(cc).SlotIndex; // 放入新的时间槽 for (int j = 0; j < cc.Duration; j++) { this.Slots[newSlotIndex + j].Classes.Add(cc); } // 验证课程节数 var count = this.Slots.FindAll(s => s.Classes.Contains(cc)).Count; Debug.Assert(cc.Duration == count, "确保排课结果中的课程的节数没有变化"); } // 重新计算适应度 this.CalculateFitnessAndEvenness(); this.SelfCheck(); }
// Bind group to class public void AddClass(CourseClass courseClass) { CourseClasses.Add(courseClass); }
// Returns TRUE if another class has same professor. public bool ProfessorOverlaps(CourseClass c) { return(Professor.Equals(c.Professor)); }
// Returns TRUE if another class has one or overlapping student groups. public bool GroupsOverlap(CourseClass c) { return(Groups.Intersect(c.Groups).Any()); }
public int GetStudentsGroupIdx(CourseClass cc) { return(this.StudentsGroups.FindIndex(sg => sg.Id == cc.StudentsGroupId)); }
private List <Slot> GetSlots(CourseClass cc) { return(this.Slots.FindAll(s => s.Classes.Contains(cc))); }