Пример #1
0
        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);
            }
        }
Пример #2
0
        /// <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;
        }
Пример #3
0
        /// <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;
        }
Пример #4
0
        /// <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;
        }
Пример #5
0
        /// <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;
        }
Пример #6
0
        public static Algorithm GetInstance()
        {
            if (instance == null)
            {
                Schedule prototype = new Schedule(2, 2, 80, 3);

                instance = new Algorithm(100, 8, 30, prototype);
            }

            return instance;
        }
Пример #7
0
        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);
                //}

            }
        }