• 第二次结对编程作业——毕设导师智能匹配


    31402631 王凌杰

    03140264 李烈争

    Coding.net链接

    问题描述

    • 目标

    实现一个毕业生导师智能分配的程序.

    • 输入

    老师:30人、老师要求选择的学生数:0~8
    学生:100人、绩点、学生的五个志愿

    • 输出

    根据输入的信息,输出选择的结果,要求一个学生只能有一个老师,一个老师可以有
    0~8个学生,未分配的老师和学生。尽可能少的学生和老师未匹配。

    问题分析

    第一次讨论的时候,我们打算将各种因素综合起来,合并成老师-学生相互选择的一个权重
    然后进行分配,这时候就遇到了下面的问题。影响选择的因素有学生的绩点,志愿,老师的
    意愿。在多因素下如何分配各个因素的权重?这个问题讨论了很久,建一个数学模型?有点
    困难?各因素乘上一个比例系数,比例系数该如何确定?人为确定吗?如何保证客观公正合理
    ?匹配一般都是对两个对象建立联系并赋予一定的权值,来体现关系的优先。那么又回到上
    面的问题。回过头将导师分配的流程走一遍发现,其实我们不用考虑这样问题。

    在流程图中,老师同意学生的选择,对老师来说,不管学生绩点的高低,都是他想要的学生,
    所以从老师的角度看,不用管这些学生的先后顺序。但从学生的角度看,绩点某种程度上体现
    这个学生那么多个学期的努力。故按绩点将所有学生排序,将绩点高的学生优先分配,然后再
    按志愿顺序分配还有名额的老师。执行三轮分配,若还有学生没有选到老师则进行人工干预。
    (不过这个概率很低)。

    编码环境

    Visual Studio 2015
    MySql
    Navicat For MySql
    语言:C#、SQL

    代码分析

    主函数

        static void Main(string[] args)
        {
            int ResultCount =0;    //结果个数
            int StudentCount =100; //学生个数
            int TeacherCount = 30; //教师个数
            
            DeleteData();          //清空数据
            Console.WriteLine("清空数据成功");
            RandomStudent(StudentCount);  //随机生成学生
            Console.WriteLine("随机学生成功");
            RandomTeacher(TeacherCount);  //随机生成教师
            Console.WriteLine("随机教师成功");
    
    
            Console.ReadLine();
    
            //第一轮选择
            StudentChoice("choice");
            Console.WriteLine("第一轮学生选导师成功");
            TeacherChoice("choice");
            Console.WriteLine("第一轮导师选学生成功");
    
            Console.ReadLine();
            //第二轮选择
            ResultCount = MySqlReadReturnCount("SELECT * FROM result");//获取结果个数
    
            //判断所有学生是否都已经分配完毕
            if (ResultCount < StudentCount)
            {
                StudentChoice("secondchoice");
                Console.WriteLine("第二轮学生选导师成功");
                TeacherChoice("secondchoice");
                Console.WriteLine("第二轮导师选学生成功");
            }
            else
            {
                Console.WriteLine("选择导师完毕");
            }
    
            Console.ReadLine();
    
            ResultCount = MySqlReadReturnCount("SELECT * FROM result");//获取结果个数
            //判断所有学生是否都已经分配完毕
            if (ResultCount < StudentCount)
            {
                StudentChoice("thirdchoice");
                Console.WriteLine("第三轮学生选导师成功");
                TeacherChoice("thirdchoice");
                Console.WriteLine("第三轮导师选学生成功");
            }
            else
            {
                Console.WriteLine("选择导师完毕");
            }
    
            Console.ReadLine();
    
    
        }
    

    主要函数分析

    随机数的生成

        private static void RandomTeacher(int TeacherNumber)//随机生成老师
        {
            string InsertString;
            string TmpID;
            string TmpStudentCount;
    
            try
            {
                for (int i = 0; i < TeacherNumber; i++)
                {
                    TmpStudentCount = NewStudentCount();//随机生成预选学生数
                    TmpID = NewID();//根据时间随机生成ID
                    InsertString = "INSERT INTO teacher(TeacherID,StudentCount,ChoiceStudentCount) VALUE('" + TmpID + "','" + TmpStudentCount + "', '0' )";
                    MySqlWrite(InsertString);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    
    
          private static void RandomStudent(int StudentNumber)//随机生成学生
        {
            string InsertString;
            string TmpID;
            string TmpGPA;
    
            try
            {
                for (int i = 0; i < StudentNumber; i++)
                {
                    TmpGPA = NewGPA();//随机生成绩点
                    TmpID = NewID();//随机生成ID
                    InsertString = "INSERT INTO student(StudentID,GPA,IsSelect) VALUE('" + TmpID + "','" + TmpGPA + "', '0' )";
                    MySqlWrite(InsertString);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    

    模拟师生互选函数

       private static void StudentChoice(string TableName)//模拟学生选择导师   TableName为进行分配操作的表名
        {
    
            //string SelectString = "select * from teacher order by rand() limit 5";
            string SelectTeacherString = "SELECT * FROM teacher WHERE StudentCount != ChoiceStudentCount";
            string SelectStudentString = "SELECT * FROM student WHERE IsSelect ="+0;
            int Count = MySqlReadReturnCount(SelectTeacherString);//还未选满的老师个数
            Console.WriteLine(Count);
            int StudentCount = MySqlReadReturnCount(SelectStudentString);//还未选中学生的个数
            string[] TeacherID = new string[5];
            string TmpID;
    
            string[] StudentID = MySqlReadArray(SelectStudentString, "StudentID");//获取还未被选中的学生ID
    
            //每个学生选5个志愿 
            for(int i = 0;i<StudentCount;i++)// StudentCount 为学生个数
            {
                TeacherID = MySqlReadRandom(SelectTeacherString, "TeacherID", Count,5);//获取随机的五个志愿老师ID
            
                for (int f = 0; f < WillCount; f++)//WillCount 为志愿个数
                {
                    TmpID = NewID();//生成ChoiceID
                    string InsertString = "INSERT INTO "+ TableName + "(ChoiceID,StudentID,TeacherID,WillNumber,IsSelect) VALUE('" + TmpID + "','" + StudentID[i] + "','" + TeacherID[f] + "','"+(f+1).ToString()+ "','" + 0 + "')";
                    MySqlWrite(InsertString);//往志愿选择表(choice)添加数据
                    Console.WriteLine(TmpID);
                }
            }
    
        }
    
         private static void TeacherChoice(string TableName)//模拟导师选择学生      TableName为进行分配操作的表名
        {
            string SelectTeacherString = "SELECT * FROM teacher WHERE StudentCount != ChoiceStudentCount"; //用于查找剩余的导师
            string SelectStudentString = "SELECT * FROM student WHERE IsSelect =" + 0;  //用于查找剩余的学生给你
            string SelectChoiceString = "SELECT * FROM "+ TableName;  //用于访问TableName表
            string UpdateChoiceString;  //用于更新TableName表
            string SelectStudentByChoiceString;  //用于获取TableName表中的StudentID
            string SelectStudentCountByTeacher;  //用于获取teacher表中的StudentCount
            //随机选择
            int ChoiceCount = MySqlReadReturnCount(SelectChoiceString);
    
            Random TmpRandom = new Random();
    
            //暂定百分之五十至百分之九十的选定
            int RandomNumber = TmpRandom.Next(ChoiceCount/2, ChoiceCount/10*9);
    
            string[] ChoiceID = MySqlReadRandom(SelectChoiceString, "ChoiceID", ChoiceCount, RandomNumber);
    
            //模拟导师选中学生
            for (int i = 0; i < RandomNumber; i++)
            {
                UpdateChoiceString = "UPDATE " + TableName + " SET IsSelect=" + 1 + " WHERE ChoiceID ='" + ChoiceID[i] + "'";//IsSelect用于判断学生在这轮是否被导师选中
                MySqlWrite(UpdateChoiceString);
                Console.WriteLine(ChoiceID[i]);
            }
    
            //进行分配
            //根据学生绩点排序开始分配老师
            string SelectStudentOrderGPA = "SELECT * FROM student  WHERE IsSelect = 0 ORDER BY GPA DESC";
            int StudentCount = MySqlReadReturnCount(SelectStudentOrderGPA);//获取还未被选中的学生个数
            Console.WriteLine(StudentCount);
    
            string[] TmpTeacherID = new string[10];
            string[] StudentID = MySqlReadArray(SelectStudentOrderGPA, "StudentID");//获取还未被选中的学生ID
           
    
            for (int i = 0; i < StudentCount; i++)
            {
                //一个学生有多条选中信息,按志愿顺序开始分配老师
                SelectStudentByChoiceString = "SELECT * FROM "+ TableName + " WHERE StudentID = '" + StudentID[i] + "' AND IsSelect = 1 ORDER BY WillNumber ASC";
                TmpTeacherID = MySqlReadArray(SelectStudentByChoiceString, "TeacherID");
                if (TmpTeacherID != null)
                {
    
                    for (int j = 0; j < TmpTeacherID.Length; j++)
                    {
                        SelectStudentCountByTeacher = "SELECT * FROM teacher WHERE TeacherID = '" + TmpTeacherID[j] + "'";
                        int TmpStudentCount = int.Parse(MySqlReadReturn(SelectStudentCountByTeacher, "StudentCount"));//获取老师要选的学生总数
                        int TmpChoiceStudentCount = int.Parse(MySqlReadReturn(SelectStudentCountByTeacher, "ChoiceStudentCount"));//获取老师已选的学生总数
    
                        if (TmpStudentCount > TmpChoiceStudentCount)//若老师人数未满
                        {
                            //Console.WriteLine(StudentID[i]);
                            MySqlWrite("INSERT INTO result(StudentID,TeacherID) VALUE('" + StudentID[i] + "','" + TmpTeacherID[j] + "')");//更新结果表
                                                                                                                                          
                            MySqlWrite("UPDATE student SET IsSelect = 1 WHERE StudentID = '" + StudentID[i] + "'");//更新学生数据为已被选中
                                                                                                                  
                            AllResultCount++;//所有结果条数
                            TmpChoiceStudentCount++;/老师已选学生数++
                            MySqlWrite("UPDATE teacher SET ChoiceStudentCount =" + TmpChoiceStudentCount + " WHERE TeacherID ='" + TmpTeacherID[j] + "'");//更新老师数据已选人数
                            Console.WriteLine(AllResultCount+"学生" + StudentID[i] + "分配成功");
                            break;/选中老师跳出循环,对下个学生进行分配
                        }
                    }
                }
    
            }
    
        }
    

    其他函数

    结果分析

    生成数据

    student表

    teacher表

    控制台界面

    第一轮选择

    模拟学生选择导师
    控制台界面

    choice表(志愿表)

    100个学生 每个学生5个志愿 总共有500条记录
    因为初始志愿导师还没有选择所以IsSelect都为0

    模拟导师选择学生
    控制台界面

    choice表

    IsSelect纪录该导师是否选择了该学生
    result表:

    student表

    IsSelect纪录学生是否中选

    重复轮数

    小结&感想

    王凌杰

    本次结对编程我学会了git的基本使用,同时也对毕设导师匹配系统有了更为深刻的理解和思考。
    本来我们也想像其他组那样用算法全自动匹配,然而考虑到很多数学建模的问题,而且感觉有很
    多不符合实际的假设。于是我们决定实现模拟人为选择,再设计匹配方式进行匹配。我们匹配思
    路主要在模拟导师选择学生之后,即实现按学生绩点来作为学生进行匹配的顺序的依据,而把志
    愿顺序作为单个学生匹配不同志愿导师的顺序依据。
    除了匹配,本次让我印象深刻的实现随机不重复的从数据库中调出数据。原本打算用"select *
    from teacher order by rand() limit 5"直接在数据库中实现,但效率出奇的低,于是便参考了
    一些算法,由于时间较赶最后决定用比较Low的list.contain 来判断。

    李烈争

    学会Git的基本使用,感谢助教推荐的Git博客,很详细。看学长的博客感叹markdown还可以那样用。
    各种锚点。可以,很强!感谢队友的大腿,编码过程中耐心的讲解,我代码的能力有待提高。考虑的
    过程中思维不够严谨,遗漏一些重要的点,拖了进度。两个人交流的时候要组织好后表达,可以提高
    效率。

  • 相关阅读:
    Seq_file文件系统实例剖析
    linux 网卡接收多播MAC(01:08开头)
    linux-3.14.13 看到mpls gso支持
    /usr/include/sys/types.h:62: error: conflicting types for ‘dev_t’
    gcc编译参数-fPIC的一些问题
    glibc-2.15编译error: linker with -z relro support required
    no CONFIG_BQL
    if_nametoindex可以检查网卡名称是否有效
    剑指offer(10)
    剑指Offer(9)
  • 原文地址:https://www.cnblogs.com/liezhengli/p/5925022.html
Copyright © 2020-2023  润新知