zoukankan      html  css  js  c++  java
  • 遗传算法实现自动组卷、随机抽题

    公司客户最近要做一个在线考试系统,其中难点在于自动组卷,因为普通的随机方法难度不好掌握,所以领导希望采用遗传算法。算法研究的任务领导交给了我,希望能在端午放假回来看到结果。而我之前并没有听说过遗传算法(孤陋寡闻),但领导分配的任务我不可能说不做(不做回家种地去),所以硬着头皮接了下来,开始GOOGLE遗传算法原理。其中一篇博文基于遗传算法自动组卷的实现对我帮助很大,同时我也联系了此博文的作者,希望能得到他的指点。没想到下午就收到回信,说这篇文章只是纯理论的研究。真正的项目早已找不到了。另外信中给了我几篇关于遗传算法的资料,给了我最直接的帮助。废话不多说,下面直接给代码,代码不难,我也不做解释,请有兴趣的童鞋自己研究(代码现在只是在测试阶段,写得很乱,将就着看吧):

    代码
    using System;
    using System.Windows.Forms;
    using System.IO;

    namespace GA
    {
        
    public partial class Form1 : Form
        {
            TTm[] TP;
            
    int _ts = 0;
            
    int n = 10;
            
    int m = 12;
            
    int Pc = 50;  //杂交的概率
            int Pm = 80;  //变异的概率
            decimal _nd = 2;
            
    int[] Fs = { 2223335555555510101010151515151520202020 };  //题目分数
            int[] Nd = { 111111222222223333444445555 };  //题目难度
            public Form1()
            {
                InitializeComponent();
            }

            
    private void button1_Click(object sender, EventArgs e)
            {
                n 
    = Fs.Length;
                m 
    = Fs.Length;
                TP 
    = new TTm[n];
                var P 
    = TP;
                
    int E, t;
                
    for (int i = 0; i < n; i++)
                {
                    P[i].T 
    = new KT[m];
                }
                Initialize(P);
                
    if (!textBox4.Text.Equals(""))
                    _nd 
    = decimal.Parse(textBox4.Text);
                t 
    = 0;
                E 
    = Evaluate(P);
                
    decimal _result = 0;
                
    while (P[E].f < 100 || _ts < 12 || Math.Round((decimal)P[E].nd / _ts, 2< _nd)  //分数小于100或者题数小于12或者难度小于2继续循环
                {
                    Crossover(P);
    //杂交 
                    Mutation(P);//变异
                    E = Evaluate(P);//评估种群
                    t = t + 1;
                    textBox1.Text 
    = t.ToString();
                    textBox2.Text 
    = P[E].f.ToString();
                    Print(P[E]);
    //输出
                    if (_ts != 0)
                    {
                        _result 
    = Math.Round((decimal)P[E].nd / _ts, 2);
                        textBox4.Text 
    = _result.ToString();//(P[E].nd /_ts)
                    }
                    Application.DoEvents();
    //使程序响应事件,避免假死无法退出现象
                    if (P[E].f == 100 && _ts >= 12 && _result >= _nd)  //总分等于100并且题数大于等于12并且难度系数大于等于2停止循环
                    {
                        _ts 
    = 0;
                        
    break;
                    }
                    Select(P);
    //择优
                }
            }

            
    /// <summary>
            
    /// 初始化种群
            
    /// </summary>
            
    /// <param name="P"></param>
            private void Initialize(TTm[] P)
            {
                
    int i, j, G;
                
    for (i = 0; i < n; i++)
                {
                    
    for (j = 0; j < m; j++)
                    {
                        P[i].T[j].Fs 
    = Fs[j];
                        P[i].T[j].nd 
    = Nd[j];
                        P[i].T[j].Se 
    = 0;
                    }
                }
                Random rnd 
    = new Random();
                
    int temp = rnd.Next(m);
                
    for (i = 0; i < n; i++)
                {
                    G 
    = 0;
                    
    while (Math.Abs(G - 105> 10 && G < 130)
                    {
                        
    if (P[i].T[temp].Se == 0)
                        {
                            P[i].T[temp].Se 
    = 1;
                            G 
    = G + P[i].T[temp].Fs;
                            P[i].T[temp].Se 
    = 0;
                        }
                    }
                }

            }

            
    /// <summary>
            
    /// 评估种群
            
    /// </summary>
            
    /// <param name="P"></param>
            private int Evaluate(TTm[] P)
            {
                
    int i, j, G, D = 0, result = 0;
                
    for (i = 0; i < n; i++)
                {
                    G 
    = 0;
                    
    for (j = 0; j < m; j++)
                    {
                        
    if (P[i].T[j].Se == 1)
                        {
                            G 
    = G + P[i].T[j].Fs;
                            D 
    = D + P[i].T[j].nd;
                        }
                    }
                    P[i].f 
    = 100 - Math.Abs(G - 100);
                    P[i].nd 
    = D;
                    
    if (P[i].f > P[result].f && P[i].nd > P[result].nd)
                        result 
    = i;
                }
                
    return result;
            }

            
    /// <summary>
            
    /// 杂交
            
    /// </summary>
            
    /// <param name="P"></param>
            private void Crossover(TTm[] P)
            {
                
    int i = 0, j = 1, k, t;
                Random rnd 
    = new Random();
                
    while (i < n - 1)
                {
                    
    if (rnd.Next(101> Pc)
                    {
                        
    //for (k = rnd.Next(m); k < m; k++)//一点杂交
                        for (k = rnd.Next(m); k <= rnd.Next(m); k++)//两点杂交
                        {
                            t 
    = P[i].T[k].Se;
                            P[i].T[k].Se 
    = P[j].T[k].Se;
                            P[j].T[k].Se 
    = t;
                        }
                    }
                    i 
    += 2; j += 1;
                }
            }

            
    /// <summary>
            
    /// 变异
            
    /// </summary>
            
    /// <param name="P"></param>
            private void Mutation(TTm[] P)
            {
                
    int i;
                Random rnd 
    = new Random();
                
    for (i = 0; i < n; i++)
                {
                    
    if (rnd.Next(101> Pm)
                    {
                        P[i].T[rnd.Next(m)].Se 
    = Convert.ToInt32(!Convert.ToBoolean(P[i].T[rnd.Next(m)].Se));
                    }
                }
            }

            
    /// <summary>
            
    /// 择优
            
    /// </summary>
            
    /// <param name="P"></param>
            private void Select(TTm[] P)
            {
                
    int i, j;
                TTm Tm;
                
    for (i = 0; i < n - 1; i++)   //对种群按优劣排序
                {
                    
    for (j = i + 1; j < n; j++)
                    {
                        
    if (P[i].f > P[j].f)
                        {
                            Tm 
    = P[i];
                            P[i] 
    = P[j];
                            P[j] 
    = Tm;
                        }
                    }
                }
                
    for (i = 0; i <= (n - 1/ 2; i++)   //淘汰50%劣等品种
                {
                    P[n 
    - 1 - i] = P[i];
                }
            }

            
    /// <summary>
            
    /// 输出
            
    /// </summary>
            
    /// <param name="Tm"></param>
            private void Print(TTm Tm)
            {
                
    string s1, s2;
                
    int i;
                _ts 
    = 0;
                s1 
    = "题号:";
                s2 
    = "分值:";
                
    for (i = 0; i < m; i++)
                {
                    
    if (Tm.T[i].Se == 1)
                    {
                        s1 
    = s1 + (i+1+ " ";
                        s2 
    = s2 + Tm.T[i].Fs + " ";
                        _ts
    ++;
                    }
                }
                textBox3.Text 
    = s1 + "\r\n" + s2 + "\r\n题数:" + _ts;
            }
        }

        
    public struct KT
        {
            
    public int Fs;
            
    public int nd;
            
    public int Se;
        }

        
    public struct TTm
        {
            
    public KT[] T;
            
    public int f;
            
    public int nd;
        }
    }

    下面的图是运行结果:

     

  • 相关阅读:
    小米9一直无限重启是怎么办
    发现一个大神做了一个ROS-ROUTEROS的中文手册中文使用说明书
    浅谈CN2 GIA和CN2 GT线路的区别
    本地ROS多线访问同一个服务器的IP,比如阿里云的IP,创建冗余线路
    syslog之三:建立Windows下面的syslog日志服务器
    增值税专用发票“抵扣联”和“发票联”丢失怎么办
    在线播放 4K 内容的需要多少带宽?
    戴尔R640服务器用H740P配置阵列
    搞微服务用阿里开源的 Nacos 真香啊!
    保持ssh不自动断开
  • 原文地址:https://www.cnblogs.com/focus_dada/p/1756593.html
Copyright © 2011-2022 走看看