protected Algorithm(int numberOfChromosomes, int replaceByGeneration, int trackBest, Schedule prototype) { // 会被后代替换掉的染色体的数量 this.replaceByGeneration = replaceByGeneration; // 当前染色体组中最好的染色体的数量,初始化为0 this.currentBestSize = 0; // 初始化的染色体 this.prototype = prototype; // 当前代,表是当前是第几代染色体 this.currentBestSize = 0; // 算法运行的状态 this.state = AlgorithmState.AS_USER_STOPED; // 算法中至少要有两条染色体 if (numberOfChromosomes < 2) numberOfChromosomes = 2; // 跟踪至少一条最好的染色体? if (trackBest < 1) trackBest = 1; if (this.replaceByGeneration < 1) this.replaceByGeneration = 1; else if (this.replaceByGeneration > numberOfChromosomes - trackBest) this.replaceByGeneration = numberOfChromosomes - trackBest; // _chromosomes与_bestFlags大小一样,它们之间有一对一的映射关系 this.chromosomes.Capacity = numberOfChromosomes; for (int i = 0; i < this.chromosomes.Capacity; i++) { chromosomes.Add(new Schedule()); } this.bestFlags.Capacity = numberOfChromosomes; for (int i = 0; i < this.bestFlags.Capacity; i++) { this.bestFlags.Add(false); } this.bestChromosomes.Capacity = trackBest; for (int i = 0; i < this.bestChromosomes.Capacity; i++) { this.bestChromosomes.Add(-1); } }
/// <summary> /// 基于复制的构造器 /// </summary> /// <param name="c"></param> /// <param name="setupOnly"></param> public Schedule(Schedule c, bool setupOnly) { if (!setupOnly) // if里是复制一个已存在的染色体 { // copy code slots = c.slots; classes = c.classes; // copy flags of class requirements criteria = c.criteria; // copy fitness fitness = c.fitness; } else // else里是新建一个染色体 { // reserve space for time-space slots in chromosomes code slots.Capacity = DAYS_NUM * DAY_HOURS * ROOM_NUM; for (int i = 0; i < slots.Capacity; i++) { slots.Add(new List<CourseClass>()); } // reserve space for flags of class requirements criteria.Capacity = COURSE_CLASS_NUM * CRITERIA_NUM; for (int i = 0; i < criteria.Capacity; i++) { criteria.Add(false); } } // copy parameters numberOfCrossoverPoints = c.numberOfCrossoverPoints; mutationSize = c.mutationSize; crossoverProbability = c.crossoverProbability; mutationProbability = c.mutationProbability; }
/// <summary> /// 随机生成一个全新的染色体 /// </summary> /// <returns></returns> public Schedule MakeNewFromPrototype(List<CourseClass> courseList) { // number of time-space slots int size = slots.Capacity; // make new chromosome, copy chromosome setup // 根据当前的染色体复制一个新的染色体,因为true为setupOnly的值,所以这里生成的染色体是全新的 Schedule newChromosome = new Schedule(this, true); // place classes at random position // 将课程放在一个随机的位置 List<CourseClass> c = courseList;// 获取所有课程,存放在类型为list的c中 foreach (CourseClass it in c)// 利用迭代器,开始遍历c { // determine random position of class int nr = ROOM_NUM; int dur = it.GetDuration(); int day = RandomNbr.GetRandomNbr() % DAYS_NUM; int room = RandomNbr.GetRandomNbr() % nr; int time = RandomNbr.GetRandomNbr() % (DAY_HOURS + 1 - dur); int pos = day * nr * DAY_HOURS + room * DAY_HOURS + time; for (int i = dur - 1; i >= 0; i--) { newChromosome.slots[pos + i].Add(it); } newChromosome.classes.Add(it, pos); } newChromosome.CalculateFitness(); return newChromosome; }
/// <summary> /// 进行交叉配对以生成新的染色体 /// </summary> /// <param name="parent2"></param> /// <returns></returns> public Schedule Crossover(Schedule parent2) { // check probability of crossover operation if (RandomNbr.GetRandomNbr() % 100 > crossoverProbability) { return new Schedule(this, false); } // new chromosome object, copy chromosome setup // n 是个全新的染色体 Schedule n = new Schedule(this, true); // number of classes int size = classes.Count; List<bool> cp = new List<bool>(); cp.Capacity = size; for (int c = 0; c < cp.Capacity; c++) { cp.Add(false); } // determine crossover point (randomly) // 随机指定的交叉位置 for (int i = numberOfCrossoverPoints; i > 0; i--) { while (true) { int p = RandomNbr.GetRandomNbr() % size; if (!cp[p]) { cp[p] = true; break; } } } // 分别获取需要进行交叉的两个课表的迭代器的首位 IDictionaryEnumerator it1 = this.classes.GetEnumerator(); IDictionaryEnumerator it2 = parent2.classes.GetEnumerator(); bool first = RandomNbr.GetRandomNbr() % 2 == 0; for (int i = 0; i < size; i++) { it1.MoveNext(); it2.MoveNext(); // crossover point if (cp[i]) { // change source chromosome first = !first; } if (first) { // insert class from first parent into new chromosome's class table if (n.classes.ContainsKey(it1.Key as CourseClass)) { n.classes.Remove(it1.Key as CourseClass); n.classes.Add(it1.Key as CourseClass, (int)it1.Value); } else { n.classes.Add(it1.Key as CourseClass, (int)it1.Value); } // all time-space slots of class are copied for (int j = (it1.Key as CourseClass).GetDuration() - 1; j >= 0; j--) { n.slots[(int)it1.Value + j].Add(it1.Key as CourseClass); } } else { // insert class from second parent into new chromosome's calss table if (n.classes.ContainsKey(it2.Key as CourseClass)) { n.classes.Remove(it2.Key as CourseClass); n.classes.Add(it2.Key as CourseClass, (int)it2.Value); } else { n.classes.Add(it2.Key as CourseClass, (int)it2.Value); } // all time-space slots of class are copied for (int j = (it2.Key as CourseClass).GetDuration() - 1; j >= 0; j--) { n.slots[(int)it2.Value + j].Add(it2.Key as CourseClass); } } } // 计算交叉后染色体的适应值 n.CalculateFitness(); return n; }
/// <summary> /// 排出课表 /// </summary> /// <param name="courseClasses">实际上课节数</param> /// <param name="days">一周上课的天数</param> /// <param name="nbr">一天上几节课</param> /// <returns></returns> public static Hashtable MakeSchedule(Hashtable courseClasses, int days, int nbr) { DataTable schedule = new DataTable(); List<Schedule> schedules = new List<Schedule>(); Hashtable courseSchedules = new Hashtable(); foreach (DictionaryEntry id in courseClasses) { if (((List<CourseClass>)id.Value).Count > days * nbr) { Exception ex = new Exception(((StudentsGroup)id.Key).GetName() + "要排的课太多了,排不下这么多课,请适量调整,谢谢Q!"); throw ex; } } IDictionaryEnumerator it = courseClasses.GetEnumerator(); for (int j = 0; j < courseClasses.Count; j++) { it.MoveNext(); // 开始排某一班的课 Algorithm instance = Algorithm.GetInstance(); Schedule.DAYS_NUM = days; // 一周上几天课 Schedule.DAY_HOURS = nbr; // 一天上几节课 Schedule.COURSE_CLASS_NUM = ((List<CourseClass>)it.Value).Count; // 实际上课节数 Schedule best = new Schedule(); instance.GetSchedule(ref ScheduleService.professors, out best, (List<CourseClass>)it.Value); courseSchedules.Add((StudentsGroup)it.Key, best); instance.Destory(); } return courseSchedules; }
public static Algorithm GetInstance() { if (instance == null) { Schedule prototype = new Schedule(2, 2, 80, 3); instance = new Algorithm(100, 8, 30, prototype); } return instance; }
public void GetSchedule(ref List<Professor> professors, out Schedule best, List<CourseClass> courseList) { //if (prototype == null) // return null; //if (state == AlgorithmState.AS_RUNNING) // return; state = AlgorithmState.AS_RUNNING; int i = 0; for (; i < chromosomes.Capacity; i++) { chromosomes[i] = prototype.MakeNewFromPrototype(courseList); //chromosomes.Add(prototype.MakeNewFromPrototype()); AddToBest(i); } // 设置当前代为0生代,属于原始人类 currentGeneration = 0; while (true) { //if (state != AlgorithmState.AS_RUNNING) //{ // break; //} // 获取最好的染色体,即获取最好的课表方案 best = GetBestChromosome(); // 当当前最好的染色体的fitness值大于等于1时,课表满足所有约束条件,停止排课 // 利用break跳出while(1) if (best.GetFitness() >= 1) { //state = AlgorithmState.AS_CRITERIA_STOPPED; for (int b = 0; b < best.GetSlots().Count; b++) { List <List< CourseClass>> slot = best.GetSlots(); if (slot[b].Count >= 1) { for (int p = 0; p < professors.Count; p++) { if (professors[p].GetId() == slot[b].First().GetProfessor().GetId()) { professors[p].AddOccupiedTime(b); } } } } return; } // 繁殖后代染色体 List<Schedule> offspring = new List<Schedule>(); // 定义后代染色体 offspring.Capacity = this.replaceByGeneration; // 设定后代染色体数量 for (int o = 0; o < offspring.Capacity; o++) // 初始化后代染色体 { offspring.Add(new Schedule()); } for (int j1 = 0; j1 < this.replaceByGeneration; j1++) { Schedule p2 = chromosomes[RandomNbr.GetRandomNbr() % chromosomes.Count]; Schedule p1 = chromosomes[RandomNbr.GetRandomNbr() % chromosomes.Count]; offspring[j1] = p1.Crossover(p2); offspring[j1].Mutation(); } // 用新繁殖后代染色体取代老一辈染色体,取代的个数为_replaceByGeneration for (int j = 0; j < replaceByGeneration; j++) { int ci; do { // 随机选择一个将被取代的染色体 ci = RandomNbr.GetRandomNbr() % chromosomes.Count; // 如果该染色体属于最好的染色之一,则重新选一个;否则进行下面的操作,用新代取代老染色体 } while (IsInBest(ci)); // 删掉老一代的染色体,换成新的染色体 chromosomes[ci] = offspring[j]; // 看这个新生代染色体是否有足够条件成为最好的染色体之一 AddToBest(ci); }// 到此,_replaceByGeneration个新生代染色体取代了_replaceByGeneration个老的染色体 currentGeneration++; //Console.WriteLine("currentGeneration is " + currentGeneration); //if (currentGeneration % 1000 == 0) //{ // //Console.WriteLine("fitness is " + best.GetFitness()); // //System.Threading.Thread.Sleep(2000); //} } }