基于遗传算法的排课系统C#代码实现

   最近是准备研究基于自适应遗传算法的排课系统,在研究这个话题之前,我对传统的遗传算法做了相应的调研,其中Python和Java都有实现的案例可以参考,没有找到合适的C#参考代码,So自己动手丰衣足食了。

借助:(225条消息) 基于遗传算法的排课算法思路_萨埵十二的博客-CSDN博客的思路,用C#完成代码编写,下面是关键代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Education.Models
{
    public class Schedule
    {
        public int etaskid;//任务id
        public string roomid;//教室id
        public string tid;//上课时间id
        public int weekday; //周几上课(1-7)
        public int slot; //第几节课(12 34 56 78 910 11)==》(1-6)


        public Schedule()
        {
        }

        public Schedule(int etaskid)
        {
            this.etaskid = etaskid;
        }
        public void random_init(List<string> rooms,int i)
        {
          Random random = new Random(int.Parse(DateTime.Now.ToString("HHmmssfff"))+i);//利用提高随机种子进行随机生成
            this.roomid = rooms.ElementAt(random.Next(rooms.Count() - 1));
            // this.tid = times.ElementAt(random.Next(times.Count() - 1)).EID;
            this.weekday = (int)(1 + random.Next(0,10) * (5 - 1 + 1));
            this.slot = (int)(1 + random.Next(0, 10) * (4 - 1 + 1));

        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Education.Models
{
    public class MyGa
    {
        private int popsize = 32;//种群规模
        private double mutprob = 0.3;//种群的变异概率
        private int elite = 15;//精英个数
        private int maxiter = 500;//进化代数(100-500)
        private List<List<Schedule>> population;
        public List<Schedule> Education(List<Schedule> schedules,List<string> roomRang)
        {
            int bestScore = 0;
            List<Schedule> bestschedule = new List<Schedule>();
           // 初始化种群
            init_population(schedules, roomRang);
            for (int i = 0; i < this.maxiter; i++)
            {
                List<List<Schedule>> newPopulation = new List<List<Schedule>>();
                //获取冲突结果
                Dictionary<List<Schedule>,int> cost_map = schedule_cost(this.population, this.elite);
                
                    foreach (List<Schedule> key in cost_map.Keys)
                    {
                        //若发现冲突结果为0,则说明咳将其当做最优排课结果返回
                        bestScore = cost_map[key];
                        if(bestScore==0)
                        {
                            bestschedule = key;
                            return bestschedule;
                        }

                    }
               
                //精英种群
                newPopulation = cost_map.Keys.ToList();
                while (newPopulation.Count < this.popsize)
                {
                    List<Schedule> temp = new List<Schedule>();
                    if((new Random().Next(0, 10) / 10.0)  < this.mutprob)
                    {
                        //落在变异概率内,变异
                        temp = Mutate(newPopulation, roomRang);
                    }
                    else
                    {
                        //交叉
                        temp = Crossover(newPopulation);
                    }
                    newPopulation.Add(temp);
                }
                this.population = newPopulation;
            }
            return bestschedule;

        }
        /// <summary>
        /// 变异 根据精英种群集合 在将其中随机一个染色体变异后 返回变异后的染色体
        /// </summary>
        /// <param name="elitePopulation"></param>
        /// <param name="roomRange"></param>
        /// <returns></returns>
        List<Schedule> Mutate(List<List<Schedule>> elitePopulation,List<string> roomRange)
        {
            Random random = new Random();
            int getIndex = random.Next(elitePopulation.Count);
            List<Schedule> ep = elitePopulation[getIndex];
            foreach (Schedule s in ep)
            {
                int pos = random.Next(3);
                if (pos == 0)
                {
                    s.roomid = roomRange[random.Next(roomRange.Count)];
                }else if (pos == 1)
                {
                    s.weekday=((int)(1 + random.Next(0, 10) * (5 - 1 + 1)));
                }else if (pos == 2)
                {
                    s.slot = (int)(1 + random.Next(0, 10) * (4 - 1 + 1));
                }
            }
            return ep;
        }
        /// <summary>
        /// 交叉
        /// </summary>
        /// <param name="elitePopulation"></param>
        /// <returns></returns>
        List<Schedule> Crossover(List<List<Schedule>> elitePopulation)
        {
            Random random = new Random();
            int getIndex1 = random.Next(elitePopulation.Count);
            int getIndex2 = random.Next(elitePopulation.Count);
            List<Schedule> e1 = elitePopulation[getIndex1];
            List<Schedule> e2 = elitePopulation[getIndex2];
            int pos = random.Next(3);
            for (int i = 0; i < e1.Count; i++)
            {
                if (pos == 0)
                {
                    e1[i].roomid = e2[i].roomid;
                }
                else if (pos == 1)
                {
                    e1[i].weekday = e2[i].weekday;
                }
                else if (pos == 2)
                {
                    e1[i].slot = e2[i].slot;
                }
            }
            return e1;
           
        }
        /**
     * 计算课表种群的冲突。
     * 返回:精英种群--精英种群中排名第一的染色体若冲突值为0则说明是可以作为最优解返回
     * 当被测试课表冲突为0的时候,这个课表就是个符合规定的课表。
     * 冲突检测遵循下面几条规则:
     * 同一个教室在同一个时间只能有一门课。
     * 同一个班级在同一个时间只能有一门课。
     * 同一个教师在同一个时间只能有一门课。
     * 但是对于目前系统中已经将班级、教师、课程拼成了一条教学任务
     * 故只需要满足 同一个教室在同一个时间 只能有一各教学任务
     * @param population
     * @param elite
     * @return
*/
        Dictionary<List<Schedule>, int> schedule_cost(List<List<Schedule>> population,int elit)
        {
            // Hashtable utilMap = new Hashtable();
            Dictionary<List<Schedule>, int> utilMap = new Dictionary<List<Schedule>, int>();
            Dictionary<List<Schedule>, int> resMap = new Dictionary<List<Schedule>, int>();
            List<int> conflicts = new List<int>();
                //一个染色体有多长==有多少课程需要安排
                int n = population[0].Count;
            foreach (List<Schedule> p in population)
            {
                int conflict = 0;
                for (int i = 0; i < n-1; i++)
                {
                    for (int j = i+1; j < n; j++)
                    {
                        //check course in same time and same room
                        //检查冲突 需保证 在同一天 同一节课 下的 同一个教室中没有两个课程
                        if (p[i].roomid.Equals(p[j].roomid) &&
                               p[i].weekday == p[j].weekday &&
                              p[i].slot == p[j].slot)
                            conflict += 1;
                    }
                }
              if( !utilMap.ContainsKey(p))
                utilMap.Add(p, conflict);
            }
            //根据冲突值排序,升序排序,并只取精英个数的量
            resMap= utilMap.OrderBy(s => s.Value).Take(elit).ToDictionary(d=>d.Key,d=>d.Value);
            

            return resMap;
        }

        public void init_population(List<Schedule> schedules,List<String> roomRange)
        {

            this.population = new List<List<Schedule>>();
            for (int i = 0; i < this.popsize; i++)
            {
                List<Schedule> entity = new List<Schedule>();
                for (int j = 0; j < schedules.Count; j++)
                {
                    Schedule temp = schedules.ElementAt(j);
                    temp.random_init(roomRange,j);
                    entity.Add(new Schedule()
                    {etaskid=temp.etaskid,
                        roomid= temp.roomid,
                        weekday= temp.weekday,
                        slot=temp.slot
                    });
                }
                this.population.Add(entity);
            }
        }
       

    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值