实例讲解遗传算法——基于遗传算法的自动组卷系统【C#版源代码】

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YiChuan
{
    public class YiChuanTest
    {
        #region 权重
        /// <summary>
        /// 知识点分布权重
        /// </summary>
        public static double kpcoverage = 0.10;

        /// <summary>
        /// 试卷难度系数权重
        /// </summary>
        public static double difficulty = 0.90;
        #endregion

        #region 调用示例
        public void Show()
        {
            DB db = new DB();
            Paper paper = new Paper()
            {
                ID = 1,
                TotalScore = 100,
                Difficulty = 0.72,
                Points = new List<int>() { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81},
                EachTypeCount = new[] { 20, 5, 10, 7, 5 },
                EachTypeSumScore = new[] { 20, 10, 20, 20, 30 }
            };

            List<Unit> unitList = CSZQ(20, paper, db.ProblemDB);
            int count = 0;
            ShowUnit(unitList);
            Console.WriteLine("-----------------------------------------------");
            double expand = 0.98;
            int runCount = 500;
            while (!IsEnd(unitList, expand))
            {
                count++;
                if (count > runCount)
                {
                    Console.WriteLine("计算 " + runCount + " 代仍没有结果,请重新设计条件!");
                    break;
                }
                unitList = Select(unitList, 10);

                unitList = Cross(unitList, 20, paper);

                if (IsEnd(unitList, expand))
                {
                    break;
                }

                unitList = Change(unitList, db.ProblemDB, paper);
                if (IsEnd(unitList, expand))
                {
                    break;
                }
                Console.WriteLine("在第 " + count + " 代未得到结果");
            }
            if (count <= runCount)
            {
                Console.WriteLine("在第 " + count + " 代得到结果,结果为:");
                Console.WriteLine("试卷难度:" + paper.Difficulty);
                ShowResult(unitList, expand);
            }
        }
        #endregion

        #region 初始种群
        public List<Unit> CSZQ(int count, Paper paper, List<Problem> problemList)
        {
            List<Unit> unitList = new List<Unit>();
            int[] eachTypeCount = paper.EachTypeCount;
            Unit unit;
            Random rand = new Random();
            for (int i = 0; i < count; i++)
            {
                unit = new Unit();
                unit.ID = i + 1;
                unit.AdaptationDegree = 0.00;
                while (paper.TotalScore != unit.SumScore)
                {
                    unit.ProblemList.Clear();
                    for (int j = 0; j < eachTypeCount.Length; j++)
                    {
                        List<Problem> oneTypeProblem = problemList
                            .Where(o => o.Type == (j + 1))
                            .Where(p => IsContain(paper, p))
                            .ToList();
                        Problem temp = new Problem();
                        for (int k = 0; k < eachTypeCount[j]; k++)
                        {
                            int index = rand.Next(0, oneTypeProblem.Count - k);
                            unit.ProblemList.Add(oneTypeProblem[index]);
                            temp = oneTypeProblem[oneTypeProblem.Count - 1 - k];
                            oneTypeProblem[oneTypeProblem.Count - 1 - k] = oneTypeProblem[index];
                            oneTypeProblem[index] = temp;
                        }
                    }
                }
                
                unitList.Add(unit);
            }
                        
                        unitList = GetKPCoverage(unitList, paper);
            unitList = GetAdaptationDegree(unitList, paper, kpcoverage, difficulty);
                                
            return unitList;
        }
        #endregion

        #region 选择算子
        public List<Unit> Select(List<Unit> unitList, int count)
        {
            List<Unit> selectedUnitList = new List<Unit>();
            double AllAdaptationDegree = 0;
            unitList.ForEach(delegate(Unit u)
            {
                AllAdaptationDegree += u.AdaptationDegree;
            });
            Random rand = new Random();
            while (selectedUnitList.Count != count)
            {
                double degree = 0.00;
                double randDegree = rand.Next(1, 100) * 0.01 * AllAdaptationDegree;
                for (int j = 0; j < unitList.Count; j++)
                {
                    degree += unitList[j].AdaptationDegree;
                    if (degree >= randDegree)
                    {
                        if (!selectedUnitList.Contains(unitList[j]))
                        {
                            selectedUnitList.Add(unitList[j]);
                        }
                        break;
                    }
                }
            }
            return selectedUnitList;
        }
        #endregion

        #region 交叉算子
        public List<Unit> Cross(List<Unit> unitList, int count, Paper paper)
        {
            List<Unit> crossedUnitList = new List<Unit>();
            Random rand = new Random();
            while (crossedUnitList.Count != count)
            {
                int indexOne = rand.Next(0, unitList.Count);
                int indexTwo = rand.Next(0, unitList.Count);
                Unit unitOne;
                Unit unitTwo;
                if (indexOne != indexTwo)
                {
                    unitOne = unitList[indexOne];
                    unitTwo = unitList[indexTwo];
                    int crossPosition = rand.Next(0, unitOne.ProblemCount - 2);
                    double scoreOne = unitOne.ProblemList[crossPosition].Score + unitOne.ProblemList[crossPosition + 1].Score;
                    double scoreTwo = unitTwo.ProblemList[crossPosition].Score + unitTwo.ProblemList[crossPosition + 1].Score;
                    if (scoreOne == scoreTwo)
                    {
                        Unit unitNewOne = new Unit();
                        unitNewOne.ProblemList = new List<Problem>();
                        unitNewOne.ProblemList.AddRange(unitOne.ProblemList);
                        Unit unitNewTwo = new Unit();
                        unitNewTwo.ProblemList = new List<Problem>();
                        unitNewTwo.ProblemList.AddRange(unitTwo.ProblemList);
                        for (int i = crossPosition; i < crossPosition + 2; i++)
                        {
                            unitNewOne.ProblemList[i] = new Problem(unitTwo.ProblemList[i]);
                            unitNewTwo.ProblemList[i] = new Problem(unitOne.ProblemList[i]);
                        }
                        unitNewOne.ID = crossedUnitList.Count;
                        unitNewTwo.ID = unitNewOne.ID + 1;
                        if (crossedUnitList.Count < count)
                        {
                            crossedUnitList.Add(unitNewOne);
                        }
                        if (crossedUnitList.Count < count)
                        {
                            crossedUnitList.Add(unitNewTwo);
                        }

                    }
                }
                crossedUnitList = crossedUnitList.Distinct(new ProblemComparer()).ToList();
            }

            crossedUnitList = GetKPCoverage(crossedUnitList, paper);
            crossedUnitList = GetAdaptationDegree(crossedUnitList, paper, kpcoverage, difficulty);
            return crossedUnitList;
        }
        #endregion

        #region 变异算子
        public List<Unit> Change(List<Unit> unitList, List<Problem> problemList, Paper paper)
        {
            Random rand = new Random();
            int index = 0;
            unitList.ForEach(delegate(Unit u)
            {
                index = rand.Next(0, u.ProblemList.Count);
                Problem temp = u.ProblemList[index];
                Problem problem = new Problem();
                for (int i = 0; i < temp.Points.Count; i++)
                {
                    if (paper.Points.Contains(temp.Points[i]))
                    {
                        problem.Points.Add(temp.Points[i]);
                    }
                }

                var otherDB = from a in problemList
                              where a.Points.Intersect(problem.Points).Count() > 0
                              select a;

                List<Problem> smallDB = otherDB.Where(p => IsContain(paper, p)).Where(o => o.Score == temp.Score && o.Type == temp.Type && o.ID != temp.ID).ToList();

                if (smallDB.Count > 0)
                {
                    int changeIndex = rand.Next(0, smallDB.Count);
                    u.ProblemList[index] = smallDB[changeIndex];
                }
            });

            unitList = GetKPCoverage(unitList, paper);
            unitList = GetAdaptationDegree(unitList, paper, kpcoverage, difficulty);
            return unitList;
        }
        #endregion

        #region 是否达到目标
        public bool IsEnd(List<Unit> unitList, double endcondition)
        {
            if (unitList.Count > 0)
            {
                for (int i = 0; i < unitList.Count; i++)
                {
                    if (unitList[i].AdaptationDegree >= endcondition)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        #endregion

        #region 题目知识点是否符合试卷要求
        private bool IsContain(Paper paper, Problem problem)
        {
            for (int i = 0; i < problem.Points.Count; i++)
            {
                if (paper.Points.Contains(problem.Points[i]))
                {
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region 计算知识点分布
        public List<Unit> GetKPCoverage(List<Unit> unitList, Paper paper)
        {
            List<int> kp;
            for (int i = 0; i < unitList.Count; i++)
            {
                kp = new List<int>();
                unitList[i].ProblemList.ForEach(delegate(Problem p)
                {
                    kp.AddRange(p.Points);
                });
                var common = kp.Intersect(paper.Points);
                unitList[i].KPCoverage = common.Count() * 1.00 / paper.Points.Count;
            }
            return unitList;
        }
        #endregion

        #region 计算试卷适应度
        public List<Unit> GetAdaptationDegree(List<Unit> unitList, Paper paper, double KPCoverage, double Difficulty)
        {
            unitList = GetKPCoverage(unitList, paper);
            for (int i = 0; i < unitList.Count; i++)
            {
                unitList[i].AdaptationDegree = 1 - (1 - unitList[i].KPCoverage) * KPCoverage - Math.Abs(unitList[i].Difficulty - paper.Difficulty) * Difficulty;
            }
            return unitList;
        }
        #endregion

        #region 显示群体
        public void ShowUnit(List<Unit> unitList)
        {
            unitList.OrderBy(o => o.ID).ToList().ForEach(delegate(Unit u)
            {
                Console.WriteLine("第" + u.ID + "套:");
                Console.WriteLine("题目数量\t知识点分布\t难度系数\t适应度");
                Console.WriteLine(u.ProblemCount + "\t\t" + u.KPCoverage.ToString("f2") + "\t\t" + u.Difficulty.ToString("f2") + "\t\t" + u.AdaptationDegree.ToString("f2"));
                //Console.WriteLine("编号\t分数\t题型\t难度系数");
                //u.ProblemList.ForEach(delegate(Problem p)
                //{
                //    Console.WriteLine(p.ID + "\t" + p.Score + "\t" + p.Type + "\t" + p.Difficulty.ToString("f2"));
                //});
                Console.WriteLine();
                Console.WriteLine();
            });
        }
        #endregion

        #region 显示结果
        public void ShowResult(List<Unit> unitList, double expand)
        {
            unitList.OrderBy(o => o.ID).ToList().ForEach(delegate(Unit u)
            {
                if (u.AdaptationDegree >= expand)
                {
                    Console.WriteLine("第" + u.ID + "套:");
                    Console.WriteLine("题目数量\t知识点分布\t难度系数\t适应度");
                    Console.WriteLine(u.ProblemCount + "\t\t" + u.KPCoverage.ToString("f2") + "\t\t" + u.Difficulty.ToString("f2") + "\t\t" + u.AdaptationDegree.ToString("f2"));
                    //Console.WriteLine("编号\t分数\t题型\t难度系数");
                    //u.ProblemList.ForEach(delegate(Problem p)
                    //{
                    //    Console.WriteLine(p.ID + "\t" + p.Score + "\t" + p.Type + "\t" + p.Difficulty.ToString("f2"));
                    //});
                    Console.WriteLine();
                    Console.WriteLine();
                }
            });
        }
        #endregion

        #region 显示一个群体题目编号
        public void ShowUnit(Unit u)
        {
            Console.WriteLine("编号\t知识点分布\t难度系数");
            Console.WriteLine(u.ID + "\t" + u.KPCoverage.ToString("f2") + "\t\t" + u.Difficulty.ToString("f2"));
            u.ProblemList.ForEach(delegate(Problem p)
            {
                Console.Write(p.ID + "\t");
            });
            Console.WriteLine();
        }
        #endregion
    }

    #region 检查是否有重得试题
    public class ProblemComparer : IEqualityComparer<Unit>
    {
        public bool Equals(Unit x, Unit y)
        {
            bool result = true;
            for (int i = 0; i < x.ProblemList.Count; i++)
            {
                if (x.ProblemList[i].ID != y.ProblemList[i].ID)
                {
                    result = false;
                    break;
                }
            }
            return result;
        }
        public int GetHashCode(Unit obj)
        {
            return obj.ToString().GetHashCode();
        }
    }
    #endregion

    #region 种群个体
    public class Unit
    {
        public Unit()
        {
            ID = 0;
            AdaptationDegree = 0.00;
            KPCoverage = 0.00;
            ProblemList = new List<Problem>();
        }
        /// <summary>
        /// 编号
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 适应度
        /// </summary>
        public double AdaptationDegree { get; set; }
        /// <summary>
        /// 难度系数
        /// </summary>
        public double Difficulty
        {
            get
            {
                double diff = 0.00;
                ProblemList.ForEach(delegate(Problem p)
                {
                    diff += p.Difficulty * p.Score;
                });
                return diff / SumScore;
            }
        }
        /// <summary>
        /// 题目数量
        /// </summary>
        public int ProblemCount
        {
            get
            {
                return ProblemList.Count;
            }
        }
        /// <summary>
        /// 总分
        /// </summary>
        public int SumScore
        {
            get
            {
                int sum = 0;
                ProblemList.ForEach(delegate(Problem p)
                {
                    sum += p.Score;
                });
                return sum;
            }
        }
        /// <summary>
        /// 知识点分布
        /// </summary>
        public double KPCoverage { get; set; }
        /// <summary>
        /// 题目
        /// </summary>
        public List<Problem> ProblemList { get; set; }
    }
    #endregion

    #region 题目实体
    public class Problem
    {
        public Problem()
        {
            ID = 0;
            Type = 0;
            Score = 0;
            Difficulty = 0.00;
            Points = new List<int>();
        }

        public Problem(Problem p)
        {
            this.ID = p.ID;
            this.Type = p.Type;
            this.Score = p.Score;
            this.Difficulty = p.Difficulty;
            this.Points = p.Points;
        }

        public int ID { get; set; }
        /// <summary>
        /// 1、2、3、4、5对应单选,多选,判断,填空,问答
        /// </summary>
        public int Type { get; set; }
        public int Score { get; set; }
        public double Difficulty { get; set; }
        public List<int> Points { get; set; }
    }
    #endregion

    #region 试卷
    public class Paper
    {
        public int ID { get; set; }
        public int TotalScore { get; set; }
        public double Difficulty { get; set; }
        public List<int> Points { get; set; }
        public int[] EachTypeCount { get; set; }
        public int[] EachTypeSumScore { get; set; }
    }
    #endregion

    #region 试题库
    public class DB
    {
        public List<Problem> ProblemDB;
        public DB()
        {
            ProblemDB = new List<Problem>();
            Problem model;
            Random rand = new Random();
            List<int> Points;
            for (int i = 1; i <= 5000; i++)
            {
                model = new Problem();
                model.ID = i;
                model.Difficulty = rand.Next(30, 100) * 0.01;
                if (i < 1001)
                {
                    model.Type = 1;
                    model.Score = 1;
                }
                if (i > 1000 && i < 2001)
                {
                    model.Type = 2;
                    model.Score = 2;
                }
                if (i > 2000 && i < 3001)
                {
                    model.Type = 3;
                    model.Score = 2;
                }
                if (i > 3000 && i < 4001)
                {
                    model.Type = 4;
                    model.Score = rand.Next(1, 5);
                }
                if (i > 4000 && i < 5001)
                {
                    model.Type = 5;
                    model.Score = model.Difficulty > 0.3 ? (int)(double.Parse(model.Difficulty.ToString("f1")) * 10) : 3;
                }
                Points = new List<int>();
                int count = rand.Next(1, 5);
                for (int j = 0; j < count; j++)
                {
                    Points.Add(rand.Next(1, 100));
                }
                model.Points = Points;
                ProblemDB.Add(model);
            }
        }
        public void ShowDB()
        {
            ProblemDB.ForEach(
                delegate(Problem p)
                {
                    Console.Write(p.ID + "\t" + p.Type + "\t" + p.Score + "\t" + p.Difficulty + "\t");
                    p.Points.ForEach(
                        delegate(int o)
                        {
                            Console.Write(o + "\t");
                        }
                    );
                    Console.WriteLine();
                });
        }
    }
    #endregion
}
时间: 2024-10-27 02:22:44

实例讲解遗传算法——基于遗传算法的自动组卷系统【C#版源代码】的相关文章

《基于遗传算法的自动组卷系统设计与实现 》17

一.基本信息 标题:<基于遗传算法的自动组卷系统设计与实现 > 时间:2016 来源:西北农林科技大学 关键字:自动组卷:遗传算法:早熟:收敛 二.研究内容 问题定义:针对传统的组卷算法组卷速度慢.成功率较低.试卷质量不高的问题,本文提出结合BP算法对遗传算法中遗传因子进行学习训练,提高染色体的适应度,采用目标试卷的题数进行实数编码替代传统的二进制编码方式,对染色体长度进行优化,解决传统遗传算法出现早熟.收敛慢的现象.利用优化的遗传算法设计并实现一个自动组卷系统. 三.流程图 四.总结 通过阅

遗传算法在自动组卷中的应用

遗传算法 遗传算法(Genetic Algorithm)是一种模拟自然界的进化规律-优胜劣汰演化来的随机搜索算法,其在解决多种约束条件下的最优解这类问题上具有优秀的表现. 1. 基本概念 在遗传算法中有几个基本的概念:基因.个体.种群和进化.基因是个体的表现,不同个体的基因序列不同:个体是指单个的生命,个体是组成种群的基础:而进化的基本单位是种群,一个种群里面有多个个体:进化是指一个种群进过优胜劣汰的自然选择后,产生一个新的种群的过程,理论上进化会产生更优秀的种群. 2. 算法流程 一个传统的遗

《基于改进随机抽取算法的信息论题库和智能组卷系统的设计与实现》

一:基本信息 1标题:<基于改进随机抽取算法的信息论题库和智能组卷系统的设计与实现> 2时间:2015 3来源:中国地质大学硕士学位论文 4关键词:随机抽取,题库,智能组卷. 二:内容: 研究意义:为了真正实现教学与考试分离,推进无纸化教学改革的浪潮,使命题组卷更加科学合理.公正公平,应用先进的计算机技术完成试题数据库系统建设,当需要考卷时,使用系统的组卷功能就可以很方便地从试题库中抽取符合要求的试题直接组成试卷.这样,不仅节省了教师宝贵的时间和精力,提高教学考试工作效率,更加客观.科学.全面

《智能组卷系统的设计与实现》16

一.基本信息 标题:<智能组卷系统的设计与实现> 时间:2017 来源:电子科技大学 关键字:智能组卷 .混合粒子群 算法 .算子 .目 标函 数 二.研究内容 问题定义:智能组卷系统是通过计算机技术和智能算法进行试题科学组卷的 .运用 智 能组卷系统可以减轻教师命题组卷的工作量 ,同时与其他组卷方式相较,利用组卷系统采用智能搜索 .匹配试题策略能够最大限度生成满足命题老师要求的试卷 ,实现对考生的科学评估同时保证测试的公平性. 智能组卷问题实质上是满足某些约束条件下的多目标参数寻优问题,常用

遗传算法(二)之组卷算法

组卷算法主要用于编制科学.公正的试卷的一种算法,具体大家可以百度看一下.我这篇文章主要是讲解如何通过遗传算法来实现组卷,遗传算法大家不清楚的地方仍然可以查看百度,不是这篇文章的重点. 一.遗传算法的表示 基本遗传算法(SGA)可以定义为一个8元数组: . 其中: C:个体的编码,SGA种一般采用固定长度的二进制编码: E:适应度评价函数: :初始种群: M:群体大小,一般取20: :选择算子: :交叉算子: :变异算子 T:结束条件 二.遗传算法的设计 遗传算法的设计通常有以下5个步骤: 1.编

基于 cobbler 实现自动安装 linux 系统

使用 cobbler 实现自动安装 centos 6.7系统 1.yum install cobbler -y 安装 cobbler ,有依赖关系,会自动把 TFTP .HTTP 服务安装上:cobbler 是基于 epel 源,需要连网 2.yum install dhcp -y 安装 DHCP 服务 3.systemctl start httpd tftp cobblerd 启动 HTTP .TFTP.cibbler ,DHCP 的配置文件不配置的话,是无法启动服务的 4.systemctl

中小学生自动出卷系统——个人项目结对编程分析

在对刘同学的代码进行学习之后,结合我自己项目的开发经验,我尝试对其代码文件作出分析,希望能在过程中收获更多,取长补短. 优点: 代码的层次分明,贯彻了面对对象设计的理念,除主类外分为login.create.accounts三个类,对应了登陆,出题,账户三个在需求中的重点部分.把界面操作.数据处理和数据存储分离. 编程风格统一,函数命名符合规则,可以清晰分辨函数与变量,并从函数名或变量命直接联系到其作用与意义.代码注释清晰,简洁,有重点. 可扩展性,可复用性,可维护性强.代码功能基本上都集成在各

基于遗传算法的高校排课系统研究

基于遗传算法的高校排课系统研究 沈丽容  陈明磊 (南京林业大学信息学院计算机科学与工程系  南京 210037)     摘  要   提出并实现了一种高校自动排课算法,利用遗传算法建立数据模型,定义一个包含教师编号.班级编号.课程编号.教室编号.上课时间段的染色体编码方案和适应度函数,通过初始化种群.选择.交叉.变异等过程不断进化,最后得到最优解.利用该算法对某高校的真实数据进行实验,结果显示无一例教室.教师.班级冲突,算法具有合理性和可行性.     关键词  遗传算法: 排课问题: 适应

基于tcpdump实例讲解TCP/IP协议

前言 虽然网络编程的socket大家很多都会操作,但是很多还是不熟悉socket编程中,底层TCP/IP协议的交互过程,本文会一个简单的客户端程序和服务端程序的交互过程,使用tcpdump抓包,实例讲解客户端和服务端的TCP/IP交互细节. TCP/IP协议 IP头和TCP头格式如下: Internet Header Format 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+