数学建模练习之1选拔问题

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_42658739/article/details/90730057

题目:

一年一度的全国大学生数学建模竞赛是高等院校的重要赛事。由于竞赛场地、经费等原因,不是所有想参加竞赛的人都能被录用。为了能够选拔出真正优秀的同学代表学校参加竞赛,数学建模指导教师需要投入大量的精力,但是每年在参赛的时候还是有很多不如意之处:有的学生言过其实,有的队员之间合作不默契,影响了数学建模的成绩。
数学建模需要学生具有较好的数学基础知识、良好的编程能力、较强的写作能力、良好的团队合作精神,同时还要求具有一定的创新能力。
在这里插入图片描述**问:**根据上表中信息,建立建模队员选拔的数学模型,要求从9名同学中选择6名组成2队参加竞赛,使得这两个参赛队有较好的竞技水平,要求模型具有可推广性。

明确问题:问题叫我们从9个人里面选6个人【并且这6个人要分为2组,每一组要有较好的竞技水平】
再次审题: 1.题目要求各方面都需要较良好,所以首先要考虑综合水平最强的。2.搭配3人一组,这三人要有所特质,取长补短。
分析:本题建立层次分析模型,逐一算出各方案层、准则层,然后做出决断选出最优秀的6个人;之后在这6个人里面,根据每个人的优势进行组队。为了便于计算,我就只选取了数学成绩、写作能力、编程能力这三个特征来作为优势度的选取。最后算出每个人的每个特征的相对本人自己的其它特征的相对优势,然后根据相对优势进行三三搭配,每个人的优势都得到发挥,要是出现几个人的相对优势最高的都出现在同一项特征里面,则选取次高的特征作为分组参考;
模型优缺点分析:使用层次分析模型会涉及人为的打相对优势权重【其实、我看来,经验的判断也属于人为的,因为经验是前人或者你自己积累出来的】;这里采取经验的赋予权重,也就是如果这个人的某项比另一项特征高分,则对于这个人来说,高分项比较重要。

代码实现:

【基于anaconda python3.7 注释包含在代码中】

# -*- coding: utf-8 -*-
# @Time    : 2019/5/22 14:41
# @Author  : data mining
# @File    : AHP.py
import numpy as np
import numpy.matlib
import heapq


class AHP:
    #所研究数据
    arry = np.array([[98,90,87,76,90,83,79,88,94],
                     ['优','良','优','良','中','优','优','良','中'],
                     [78,90,69,96,84,96,82,79,95],
                     ['良','良','差','优','良','优','优','优','中'],
                     ['优','中','优','中','优','良','良','良','中']])
    resxx = []
    # res1 = []
    def __init__(self):
        self.resxx = self.resxx
        self.arry1 = np.copy(self.arry)  #备用
        self.arry2 = np.copy(self.arry)

    def get_matrixA(self,data1,data2):  #获得准则层 判别矩阵A
        matrix = np.matlib.ones((len(data1),len(data2)))  #生成以1填充的矩阵
        matrix = np.asarray(matrix)
        #交叉比较
        for i in range(0,len(data1)):
                for j in range(0, len(data2)):
                    if data1[i] - data2[j] == 4:
                        matrix[i][j] = 4.0
                    elif data1[i] - data2[j] == 3:
                        matrix[i][j] = 5.0
                    elif data1[i] - data2[j] == 2:
                        matrix[i][j] = 3.0
                    elif data1[i] - data2[j] == 1:
                        matrix[i][j] = 2.0
                    elif data1[i] - data2[j] == 0:
                        matrix[i][j] = 1.0
                    elif data1[i] - data2[j] == -4:
                        matrix[i][j] = 1 / 4
                    elif data1[i] - data2[j] == -3:
                        matrix[i][j] = 1 / 5
                    elif data1[i] - data2[j] == -2:
                        matrix[i][j] = float(str(1 / 3)[:4])
                    elif data1[i] - data2[j] == -1:
                        matrix[i][j] = 1 / 2
        matrixA = np.asmatrix(matrix)
        print("matrixA:")
        print(matrixA)
        return matrixA  #判别矩阵A

    def get_matrixB(self,data1,data2): #获得方案层 判别矩阵B
        matrix = np.matlib.ones((9,9))
        matrix = np.asarray(matrix)
        if type(data1[0]) is float:
            for i in range(0, len(data1)):
                for j in range(0, len(data2)):
                    if i == j:
                        matrix[i][j] = 1.0
                    else:
                        if data1[i] == data2[j]:
                            matrix[i][j] = 1.0
                        elif data1[i] > data2[j]: ##行大于列
                            if (data1[i]-data2[j]) <=2:
                                matrix[i][j] = 1.0
                            elif 3<=(data1[i]-data2[j]) <5:
                                matrix[i][j] = 2.0
                            elif 5<=(data1[i]-data2[j]) <6:
                                matrix[i][j] = 3.0
                            elif 6<=(data1[i]-data2[j]) <8:
                                matrix[i][j] = 4.0
                            else:
                                matrix[i][j] = 5.0

                        elif data1[i] < data2[j]:  #行小于列
                            if (data1[i] - data2[j])>= -3:
                                matrix[i][j] = 1.0
                            elif -5 <(data1[i]-data2[j]) <-3:
                                matrix[i][j] = float(str(1/3)[:4])
                            else:
                                matrix[i][j] = 1/5
        else:
            for i in range(0, len(data1)):
                for j in range(0, len(data2)):
                    if i == j:
                        matrix[i][j] = str(1.0)
                    else:
                        if data1[i] == data2[j]:
                            matrix[i][j] = str(1.0)
                        elif data1[i]=='优' and data2[j]=='良':
                            matrix[i][j] = str(3.0)
                        elif data1[i]=='优' and data2[j]=='中':
                            matrix[i][j] = str(5.0)
                        elif data1[i]=='优' and data2[j]=='差':
                            matrix[i][j] = str(9.0)
                        elif data1[i]=='良' and data2[j]=='优':
                            matrix[i][j] = str(str(1/3)[:4])
                        elif data1[i]=='良' and data2[j]=='中':
                            matrix[i][j] = str(4.0)
                        elif data1[i]=='良' and data2[j]=='差':
                            matrix[i][j] = str(7.0)
                        elif data1[i]=='中' and data2[j]=='优':
                            matrix[i][j] = str(1/5)
                        elif data1[i]=='中' and data2[j]=='良':
                            matrix[i][j] = str(1/4)
                        elif data1[i]=='中' and data2[j]=='差':
                            matrix[i][j] = str(3.0)
                        elif data1[i]=='差' and data2[j]=='优':
                            matrix[i][j] = str(str(1/9)[:4])
                        elif data1[i]=='差' and data2[j]=='良':
                            matrix[i][j] = str(str(1/7)[:4])
                        elif data1[i]=='差' and data2[j]=='中':
                            matrix[i][j] = str(str(1/3)[:4])

            matrix = np.asarray(matrix,dtype=float)
        matrixB = np.asmatrix(matrix)
        return matrixB #判别矩阵B

    def getA_function(self): #准则层判别矩阵 5*5
        abilityList = [5,4,3,2,1]
        matrixA = AHP.get_matrixA(self,data1=abilityList,data2=abilityList) # 判别矩阵
        VectorA,RootA = AHP.get_Vector_Root(self,matrixA)
        print("\nA:")
        print("VectorA:\n", VectorA)
        print("RootA:\n", RootA)
        return VectorA,RootA

    def get_Vector_Root(self,dataArray):  #特征根和特征向量
        dataArray = np.asarray(dataArray)
        dataCenter = np.copy(dataArray)
        # dataCenter按列求和
        columnMatrixCenter = dataCenter.sum(axis=0)
        for i in range(1, len(dataArray) + 1):  # dataCenter列向量归一化
            dataCenter[:, i - 1:i] = dataCenter[:, i - 1:i] * (1 / columnMatrixCenter[i - 1])
        # dataCenter行向量求和
        linedataCenter = np.asarray(np.asmatrix(np.asarray(dataCenter.sum(axis=1))).T)
        # linedataCenter按列求和  【只有一列求和了】
        columnLinedataCenter = linedataCenter.sum(axis=0)
        for i in range(1, len(linedataCenter)):  # linedataCenter列向量归一化
            linedataCenter[:, i - 1:i] = linedataCenter[:, i - 1:i] * (1 / columnLinedataCenter)
        vector = linedataCenter  # 特征向量
        root = dataArray @ vector
        sumi = 0
        for i in range(0,len(dataArray)):
            sumi += root[i] / vector[i]
        Rootmax = (1 / len(dataArray)) * sumi  #最大特征根
        return vector, Rootmax

    def getB_function(self):  #计算方案层 判别矩阵  Value特征根  Vector特征向量   #B1~B5矩阵 9*9
        mathTrixB = AHP.get_matrixB(self,data1=list(map(float,list(self.arry2[0]))),data2=list(map(float,list(self.arry2[0]))))

        mathVectorB,mathRootBmax = AHP.get_Vector_Root(self,mathTrixB)
        print("\nmath:")
        print("mathVectorB:\n", mathVectorB)
        print("mathRootBmax:\n", mathRootBmax)
        writeTrixB = AHP.get_matrixB(self, data1=list(self.arry2[1]), data2=list(self.arry2[1]))

        writeVectorB, writeRootBmax = AHP.get_Vector_Root(self, writeTrixB)
        print("\nwrite:")
        print("writeVectorB:\n", writeVectorB)
        print("writeRootBmax:\n", writeRootBmax)
        codeTrixB = AHP.get_matrixB(self,data1=list(map(float,list(self.arry2[2]))),data2=list(map(float,list(self.arry2[2]))))

        codeVectorB, codeRootBmax = AHP.get_Vector_Root(self, codeTrixB)
        print("\ncode:")
        print("codeVectorB:\n", codeVectorB)
        print("codeRootBmax:\n", codeRootBmax)
        teamTrixB = AHP.get_matrixB(self,data1=list(self.arry2[3]),data2=list(self.arry2[3]))

        teamVectorB,teamRootBmax = AHP.get_Vector_Root(self, teamTrixB)
        print("\nteam:")
        print("teamVectorB:\n", teamVectorB)
        print("teamRootBmax:\n", teamRootBmax)
        createTrixB = AHP.get_matrixB(self,data1=list(self.arry2[4]),data2=list(self.arry2[4]))

        createVectorB, createRootBmax = AHP.get_Vector_Root(self, createTrixB)
        print("\ncreate:")
        print("createVectorB:\n", createVectorB)
        print("createRootBmax:\n", createRootBmax)
        rootB = [mathRootBmax,writeRootBmax,codeRootBmax,teamRootBmax,createRootBmax]
        vectorB = [mathVectorB,writeVectorB,codeVectorB,teamVectorB,createVectorB]
        # root 特征根
        #vector 特征向量
        return rootB,vectorB

    def CR(self,vector,root): #计算一致性比率CR和一致性指标CI
        # n = len(array)  5的时候n = 1.12   9的时候n = 1.45【查表得知】
        if(len(vector)==5):
            RI=1.12
            CI = (root-len(vector)) / (len(vector)-1)
            CR = CI/RI
        else:
            RI = 1.45
            CI = (root - len(vector)) / (len(vector) - 1)
            CR = CI / RI
        return CR,CI

    def judge_choose(self):
        VectorA,RootA = AHP.getA_function(self)
        CRA,CIA = AHP.CR(self,VectorA,RootA)  #通过检测
        print("CRA",CRA)
        print("CIA",CIA)
        listRootB, listVectorB = AHP.getB_function(self)
        list_CRB = [] #通过检测
        list_CIB = []
        for i in range(0,5):
            CR,CI = AHP.CR(self,listVectorB[i],listRootB[i])
            list_CRB.append(CR)
            list_CIB.append(CI)
        # print("准则层判别矩阵的CR: ",CRA,"\n方案层判别矩阵的CR:",list_CRB)
        list_CR = list_CRB.copy()
        list_CR.append(CRA)
        print("B1~B5: CR:\n", list_CRB)
        print("B1~B5:  CI: \n", list_CIB)
        testList = []
        for i in list_CR:
            if i[0]<0.1:
                testList.append(1)
        # 所有判别矩阵的CR都小于0.1,不一致性程度在容许范围内,此时特征向量作为权向量。
        # self.resxx = []
        if sum(testList) == 6:
                self.arry = np.hstack([listVectorB[0], listVectorB[1]])
                for i in range(2,5):
                    self.arry = np.hstack([self.arry, listVectorB[i]])
                # 选人
                reslute = [] #存储人的序号 的列表
                for i in range(0,9):
                    reslute.append((self.arry@VectorA)[i][0])
                self.res1 = list(map(reslute.index, heapq.nlargest(6, reslute)))
                self.resxx = [i+1 for i in self.res1]


        else:
            pass
        self.res1 = self.res1
        print("选中的人的矩阵行号:",self.res1)
        print("被命运选中的人",self.resxx)
        return self.resxx,self.res1

    def grouping(self):
        chooseNum,res = AHP.judge_choose(self)
        self.arry1 = np.asarray(np.asmatrix(self.arry1).T)
        self.target = np.vstack([self.arry1[res[0]],self.arry1[res[1]]])
        for i in range(2,6):
            self.target = np.vstack([self.target,self.arry1[res[i]]])
        self.target = np.asarray(np.asmatrix(self.target))[:,:3]
        for i in range(0,len(self.target)):
            for j in range(0,len(self.target[i])):
                if self.target[i][j] == '优':
                    self.target[i][j] = '95'
                elif self.target[i][j] == '良':
                    self.target[i][j] = '85'
                elif self.target[i][j] == '中':
                    self.target[i][j] = '75'
                elif self.target[i][j] == '差':
                    self.target[i][j] = '65'
        self.target = np.asarray(self.target,dtype=float)
        cmean = self.target.mean(axis=0) #按列求均值
        cstd = self.target.std(axis=0) #求标准差
        relative_adv = (self.target-cmean)/cstd  #相对优势
        print("相对优势矩阵:\n",relative_adv)

        relative_adv_Max = np.max(relative_adv, axis=1)  #按行
        maxAdv = []
        for i in range(0,len(relative_adv_Max)):
            maxAdv.append(float(relative_adv_Max[i]))
        # print("各人最大相对优势:\n", maxAdv)
        position = []
        relative_adv_matrix = np.asmatrix(relative_adv)
        for value in range(0,len(maxAdv)):
            index = np.argwhere(relative_adv_matrix == maxAdv[value])
            if value == 3:
                position.append(index[2])
            elif value == 4:
                position.append(index[3])
            else:
                position.append(index)
        print("各人的最大相对优势在矩阵中的坐标:\n",np.asarray(position).reshape(6,1))

        self.group = []
        for i in range(0,len(chooseNum)):
            self.group.append([chooseNum[i],self.target[i]])
        print("被选中的6人的分数\n",np.asarray(self.group))
        allList = [] #在满足条件下,所有可能分组
        firstList = []
        secondList = []
        manTime = []
        chooseOne = chooseNum.copy()
        chooseTWo = chooseNum.copy()
        for i in range(1,4):
            #0-1 1-2 2-3
            if i == 1:
                coumIndex = np.argwhere(relative_adv_matrix == float(np.max(relative_adv[:, i - 1:i], axis=0)[0]))
                manTime.append(coumIndex[0][0])
                firstList.append(chooseNum[int(coumIndex[0][0])])  #添加第几号人
                chooseOne.remove(chooseOne[int(coumIndex[0][0])])
                secondList.append(chooseNum[int(coumIndex[0][0])])  # 添加第几号人
                chooseTWo.remove(chooseTWo[int(coumIndex[0][0])])

            elif i == 2:
                coumIndex = np.argwhere(relative_adv_matrix == float(np.max(relative_adv[:, i - 1:i], axis=0)[0]))
                coumIndex2 = coumIndex

                i = 3
                coumIndex3 = np.argwhere(relative_adv_matrix == float(np.max(relative_adv[:, i - 1:i], axis=0)[0]))
                manTime.append(coumIndex3[0][0])
                firstList.append(chooseNum[int(coumIndex3[0][0])])
                chooseOne.remove(chooseOne[int(coumIndex3[0][0])-1])
                secondList.append(chooseNum[int(coumIndex3[0][0])])
                chooseTWo.remove(chooseTWo[int(coumIndex3[0][0]) - 1])
                for j in range(0, len(coumIndex2)):
                    if coumIndex2[j][0] == manTime[0]:
                        pass
                    elif coumIndex2[j][0] == manTime[1]:
                        pass
                    else:
                        if coumIndex2[j][0] == 3:
                            firstList.append(chooseNum[int(coumIndex2[j][0])])
                            chooseOne.remove(chooseOne[int(coumIndex2[0][0])-3])
                            allList.append((firstList,chooseOne))

                        if coumIndex2[j][0] == 4:
                            secondList.append(chooseNum[int(coumIndex2[j][0])])
                            chooseTWo.remove(chooseTWo[int(coumIndex2[0][0]) - 2])
                            allList.append((secondList, chooseTWo))

            elif i == 3:
                pass
        return allList



    def main(self):
        chooseGroup = AHP.grouping(self)
        for i in range(0,len(chooseGroup)):
            print("第{}种有效的分组:".format(i+1),chooseGroup[0])



if __name__ == '__main__':
    a = AHP()
    a.main()
    print("【查RI表得知】:")
    print("RI: n=5的时候 RI5=1.12 ; n=9的时候 RI9=1.45")

分组结果:请粘贴代码运行

猜你喜欢

转载自blog.csdn.net/qq_42658739/article/details/90730057
今日推荐