层次分析法(AHP)是美国运筹学家匹茨堡大学教授萨蒂(T.L.Saaty)于上世纪70年代初,为美国国防部研究“根据各个工业部门对国家福利的贡献大小而进行电力分配”课题时,应用网络系统理论和多目标综合评价方法,提出的一种层次权重决策分析方法。
这种方法的特点是在对复杂的决策问题的本质、影响因素及其内在关系等进行深入分析的基础上,利用较少的定量信息使决策的思维过程数学化,从而为多目标、多准则或无结构特性的复杂决策问题提供简便的决策方法。
层次分析法是对难于完全定量的复杂系统作出决策的模型和方法。
层次分析法概述
人们在对社会、经济以及管理领域的问题进行系统分析时,面临的经常是一个由相互关联、相互制约的众多因素构成的复杂系统。层次分析法则为研究这类复杂的系统,提供了一种新的、简洁的、实用的决策方法。
层次分析法(AHP法)是一种解决多目标的复杂问题的定性与定量相结合的决策分析方法。该方法将定量分析与定性分析结合起来,用决策者的经验判断各衡量目标能否实现的标准之间的相对重要程度,并合理地给出每个决策方案的每个标准的权数,利用权数求出各方案的优劣次序,比较有效地应用于那些难以用定量方法解决的课题。
层次分析法是社会、经济系统决策中的有效工具。其特征是合理地将定性与定量的决策结合起来,按照思维、心理的规律把决策过程层次化、数量化。是系统科学中常用的一种系统分析方法。
该方法自1982年被介绍到我国以来,以其定性与定量相结合地处理各种决策因素的特点,以及其系统灵活简洁的优点,迅速地在我国社会经济各个领域内,如工程计划、资源分配、方案排序、政策制定、冲突问题、性能评价、能源系统分析、城市规划、经济管理、科研评价等,得到了广泛的重视和应用。
层次分析法的三大典型应用
(1)用于最佳方案的选取(选择运动员、选择地址)
(2)用于评价类问题(评价水质状况、评价环境)
(3)用于指标体系的优选(兼顾科学和效率)
层次分析法的基本原理
层次分析法根据问题的性质和要达到的总目标,将问题分解为不同的组成因素,并按照因素间的相互关联影响以及隶属关系将因素按不同层次聚集组合,形成一个多层次的分析结构模型,从而最终使问题归结为最低层(供决策的方案、措施等)相对于最高层(总目标)的相对重要权值的确定或相对优劣次序的排定。
层次分析法的步骤和方法
运用层次分析法构造系统模型时,大体可以分为以下四个步骤:
(1)建立层次结构模型
(2)构造判断(成对比较)矩阵
(3)层次单排序及其一致性检验
(4)层次总排序及其一致性检验
建立层次结构模型
将决策的目标、考虑的因素(决策准则)和决策对象按它们之间的相互关系分最高层、中间层和最低层,绘出层次结构图。
最高层:决策的目的、要解决的问题。
最低层:决策时的备选方案。
中间层:考虑的因素、决策的准则。
对于相邻的两层,称高层为目标层,低层为因素层。下面举例说明。
例1.大学毕业生就业选择问题
获得大学毕业学位的毕业生,在“双向选择”时,用人单位与毕业生都有各自的选择标准和要求。就毕业生来说选择单位的标准和要求是多方面的,例如:
①能发挥自己才干作出较好贡献(即工作岗位适合发挥自己的专长)
②工作收入较好(待遇好)
③生活环境好(大城市、气候等工作条件等)
④单位名声好(声誉等)
⑤工作环境好(人际关系和谐等)
⑥发展晋升机会多(如新单位或前景好)等。
那么就可以建立如下的模型:
例2.选择旅游目的地
如何在3个目的地中按照景色、费用、居住条件等因素选择,可建立如下模型:
层次分析法的思维过程归纳
将决策问题分为3个或多个层次:
最高层:目标层。表示解决问题的目的,即层次分析要达到的总目标。通常只有一个总目标。
中间层:准则层、指标层、…。表示采取某种措施、政策、方案等实现预定总目标所涉及的中间环节;又分准则层、指标层、策略层、约束层等。
最低层:方案层。表示将选用的解决问题的各种措施、政策、方案等。通常有几个方案可选。
每层有若干元素,层间元素的关系用相连直线表示。
层次分析法所要解决的问题是关于最低层对最高层的相对权重问题,按此相对权重可以对最低层中的各种方案、措施进行排序,从而在不同的方案中作出选择或形成选择方案的原则。
构造判断(成对比较)矩阵
在确定各层次各因素之间的权重时,如果只是定性的结果,则常常不容易被别人接受,因而Santy等人提出:一致矩阵法,即:
1.不把所有因素放在一起比较,而是两两相互比较
2.对此时采用相对尺度,以尽可能减少性质不同的诸因素相互比较的困难,以提高准确度。
判断矩阵是表示本层所有因素针对上一层某一个因素的相对重要性的比较。判断矩阵的元素a_{ij},用Santy的1—9标度方法给出。
心理学家认为成对比较的因素不宜超过9个,即每层不要超过9个因素。
判断矩阵元素a_{ij}的标度方法
标度 | 含义 |
1 | 表示两个因素相比具有同样的重要性 |
3 | 表示两个因素相比,一个因素比另一个因素稍微重要 |
5 | 表示两个因素相比,一个因素比另一个因素明显重要 |
7 | 表示两个因素相比,一个因素比另一个因素强烈重要 |
9 | 表示两个因素相比,一个因素比另一个因素极端重要 |
2,4,6,8 | 上述两相邻判断的中值 |
倒数 | 因素i与j比较的判断a_{ij},则因素j与i比较的判断a_{ji}=\frac{1}{a_{ij}} |
命名元素与构造矩阵
以例2选择旅游目的地为例:
目标层:O(选择旅游地)
准则层:C1-景色;C2-费用;C3-居住;C4-饮食;C5-旅途
假设要比较各个准则对目标O的重要性,由矩阵A可以确定C_1,C_2,...,C_n对O的权向量
A~成对比较阵,A是正互反阵
C_i:C_j=a_{ij} \qquad A=(a_{ij})_{n \times n},a_{ij}>0,a_{ji}=\frac{1}{a_{ij}}
假设A的数据如下:
A=\left [ \begin{aligned} &1\quad&&1/2\quad&&4\quad&&3\quad&&3\\ &2\quad&&1\quad&&7\quad&&5\quad&&5\\ &1/4\quad&&1/7\quad&&1\quad&&1/2\quad&&1/3\\ &1/3\quad&&1/5\quad&&2\quad&&1\quad&&1\\ &1/3\quad&&1/5\quad&&3\quad&&1\quad&&1\\ \end{aligned}\right]
经过比较可以发现A在数据上存在不一致的情况。在实际操作中允许出现不一致,但要确定不一致的允许范围。
考察完全一致的情况
满足a_{ij}·a{jk}=a_{ik},i,j,k=1,2,...,n的正互反阵A称为一致阵
一致阵具有如下性质:
1.A的秩为1,A的唯一非零特征根为n,且满足Aω=nω
2.非零特征根n所对应的特征向量归一化后可以作为权向量
对于不一致(但在允许范围内)的成对比较阵A,建议用对应于最大特征根λ的特征向量作为权向量ω,即Aω=λω
对于例2中的A,使用python计算最大特征根和权向量的代码实现如下:
import numpy as np
#构造矩阵
A=np.array([[1,1/2,4,3,3],
[2,1,7,5,5],
[1/4,1/7,1,1/2,1/3],
[1/3,1/5,2,1,1],
[1/3,1/5,3,1,1]])
#计算行数与列数
[m,n]=A.shape
#求特征值和特征向量
V,D=np.linalg.eig(A)
#求最大特征值
eig_val=np.max(V)
#求最大特征向量
k=[i for i in range(len(V)) if V[i] == np.max(V)]
eig_vec=-D[:,k]
#赋权重
weight_vec=np.zeros((n,1))
for i in range(0,n):
weight_vec[i]=eig_vec[i]/np.sum(eig_vec)
W=weight_vec
print(f'最大特征根为:{eig_val}')
print("权向量为:")
print(W)
最大特征根为:(5.072084408570216+0j) 权向量为: [[0.26360349] [0.47583538] [0.0538146 ] [0.09806829] [0.10867824]]
层次单排序及其一致性检验
原理阐释
对应于判断矩阵最大特征根λ_{max}的特征向量,经归一化(使向量中各元素之和等于1)后记为W。
W的元素为同一层次因素对于上一层次因素某因素相对重要性的排序权值,这一过程称为层次单排序。
能否确认层次单排序,需要进行一致性检验,所谓一致性检验是指对A确定不一致的允许范围。
定理:n阶一致阵的唯一非零特征根为n
定理:n阶正互反阵A 的最大特征根λ≥n,当且仅当a=n时A为一致阵
由于入连续的依赖于a_{ij},则a比n大的越多,A的不一致性越严重。用最大特征值对应的特征向量作为被比较因素对上层某因素影响程度的权向量,其不一致程度越大,引起的判断误差越大。因而可以用λ-n数值的大小来衡量A的不一致程度。
定义一致性指标可以用以下的公式来表示:
CI=\frac{λ-n}{n-1}
CI=0,有完全的一致性;CI接近于0,有满意的一致性;CI越大,不一致越严重
为了衡量CI的大小,引入随机一致性指标RI。方法为随即构造500个成对比较阵A_1,A_2,...,A_{500},则可以获得一致性指标CI_1,CI_2,...,CI_{500},随后我们可以得到RI的计算公式:
RI=\frac{CI_1+CI_2+...+CI_{500}}{500}=\frac{\frac{λ_1+λ_2+...+λ_{500}}{500}-n}{n-1}
其中RI根据指标个数n可以通过下表选择对应的RI值:
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
RI | 0 | 0 | 0.58 | 0.90 | 1.12 | 1.24 | 1.32 | 1.41 | 1.45 | 1.49 | 1.52 | 1.54 | 1.56 | 1.58 | 1.59 |
我们定义一致性比率为:
CR=\frac{CI}{RI}
一般情况下当一致性比率CR<0.1时认为A的不一致程度在容许范围内,有满意的一致性,通过一致性检验。可用其归一化特征向量作为权向量,否则要重新构造成对比较矩阵A,对其中元素加以调整
代码实现
对于例2的A,使用python进行一致性校验的步骤如下:
import numpy as np
#构造矩阵
A=np.array([[1,1/2,4,3,3],
[2,1,7,5,5],
[1/4,1/7,1,1/2,1/3],
[1/3,1/5,2,1,1],
[1/3,1/5,3,1,1]])
#计算行数与列数
[m,n]=A.shape
#求特征值和特征向量
V,D=np.linalg.eig(A)
#求最大特征值
eig_val=np.max(V)
#求最大特征向量
k=[i for i in range(len(V)) if V[i] == np.max(V)]
eig_vec=-D[:,k]
#一致性检验
CI=(eig_val-n)/(n-1)
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59]
#判断是否通过一致性检验
CR=CI/RI[n-1]
print(f'CI={CI}\nRI={RI[n-1]}\nCR={CR}')
if CR>=0.1:
print('没有通过一致性检验\n')
else:
print('通过一致性检验\n')
CI=(0.018021102142554035+0j) RI=1.12 CR=(0.01609026977013753+0j) 通过一致性检验
封装成对比较矩阵类
我们综合以上两个步骤可以构造出一个成对比较矩阵类来封装这些属性和方法,方便我们的后续操作:
import numpy as np
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#计算最大特征向量
def calEigVec(self):
k=[i for i in range(len(self.V)) if self.V[i] == np.max(self.V)]
return -self.D[:,k]
#分配权向量
def giveWeight(self):
weight_vec=np.zeros((self.n,1))
for i in range(0,self.n):
weight_vec[i]=self.eig_vec[i]/np.sum(self.eig_vec)
return weight_vec
#检验一致性
def checkConsistency(self):
if self.CR>=0.1:
return False
else:
return True
def __init__(self,elem):
#RI标准值
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59]
self.elem=elem #元素
self.n=self.elem.shape[1] #阶数
self.V=np.linalg.eig(self.elem)[0] #特征值
self.D=np.linalg.eig(self.elem)[1] #特征向量
self.eig_val=np.max(self.V) #最大特征值
self.eig_vec=self.calEigVec() #最大特征向量
self.W=self.giveWeight() #权向量
self.CI=(self.eig_val-self.n)/(self.n-1) #一致性指标
self.RI=RI[self.n-1] #采用的随机一致性指标
self.CR=self.CI/self.RI #一致性比率
self.accepted=self.checkConsistency() #是否通过一致性检验
def __str__(self):
s1=f'elem=\n{self.elem}\n'
s2=f'n={self.n}\n'
s3=f'V=\n{self.V}\n'
s4=f'D=\n{self.D}\n'
s5=f'eig_val={self.eig_val}\n'
s6=f'eig.vec=\n{self.eig_vec}\n'
s7=f'W=\n{self.W}\n'
s8=f'CI={self.CI}\n'
s9=f'RI={self.RI}\n'
s10=f'CR={self.CR}\n'
s11=f'accepted={self.accepted}'
return(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11)
#构造矩阵
A_e=np.array([[1,1/2,4,3,3],
[2,1,7,5,5],
[1/4,1/7,1,1/2,1/3],
[1/3,1/5,2,1,1],
[1/3,1/5,3,1,1]])
A=PairwiseComparisonMatrix(A_e)
print(A)
elem= [[1. 0.5 4. 3. 3. ] [2. 1. 7. 5. 5. ] [0.25 0.14285714 1. 0.5 0.33333333] [0.33333333 0.2 2. 1. 1. ] [0.33333333 0.2 3. 1. 1. ]] n=5 V= [ 5.07208441+0.j -0.03070462+0.60082743j -0.03070462-0.60082743j -0.00533758+0.05475206j -0.00533758-0.05475206j] D= [[-0.46582183+0.j -0.44186009-0.27105866j -0.44186009+0.27105866j -0.36716196+0.2414553j -0.36716196-0.2414553j ] [-0.84086331+0.j -0.77734237+0.j -0.77734237-0.j 0.85752776+0.j 0.85752776-0.j ] [-0.09509743+0.j 0.02000217+0.15570733j 0.02000217-0.15570733j -0.0190312 +0.00635723j -0.0190312 -0.00635723j] [-0.17329948+0.j 0.02610008-0.07828144j 0.02610008+0.07828144j -0.07374757-0.21459801j -0.07374757+0.21459801j] [-0.19204866+0.j 0.28288299-0.12469508j 0.28288299+0.12469508j 0.07483506+0.11850604j 0.07483506-0.11850604j]] eig_val=(5.072084408570216+0j) eig.vec= [[0.46582183-0.j] [0.84086331-0.j] [0.09509743-0.j] [0.17329948-0.j] [0.19204866-0.j]] W= [[0.26360349] [0.47583538] [0.0538146 ] [0.09806829] [0.10867824]] CI=(0.018021102142554035+0j) RI=1.12 CR=(0.01609026977013753+0j) accepted=True
层次总排序及其一致性检验
原理阐释
计算某一层次所有因素对于最高层(总目标)相对重要性的权值,称为层次总排序。
这一过程是从最高层次到最低层次依次进行的。
A层m个因素A_1,A_2,...,A_m对总目标Z的排序为a_1,a_2,...,a_m
B层n个因素对上层A中因素A_j的层次单排序为b_{1j},b_{2j},...,b_{nj}(j=1,2,...,m)
总结B层的层次总排序为:
B_1:a_1b_{11}+a_2b_{12}+...+a_mb_{1m}\\ B_2:a_1b_{21}+a_2b_{22}+...+a_mb_{2m}\\ ......\\ B_n:a_1b_{n1}+a_2b_{n2}+...+a_mb_{nm}\\
即B层第i个因素对总目标的权值为\sum^{m}_{j=1}a_jb_{ij}
设B层对上层(A层)中因素A_j(j=1,2,…,m)的层次单排序一致性指标为CI_j,随机一致性指标为RI_j,则层次总排序的一致性比率为:
CR=\frac{a_1CI_1+a_2CI_2+...+a_mCI_m}{a_1RI_1+a_2RI_2+...+a_mRI_m}
当CR<0.1时,认为层次总排序通过一致性检验,层次总排序具有满意度一致性,否则需要重新调整那些一致性比率高的判断矩阵的元素取值
代码实现
我们假设例2中B层构造的成对比较矩阵如下:
B_1=\left [ \begin{aligned} &1\quad&&2\quad&&5\\ &1/2\quad&&1\quad&&2\\ &1/5\quad&&1/2\quad&&1\\ \end{aligned}\right] B_2=\left [ \begin{aligned} &1\quad&&1/3\quad&&1/8\\ &3\quad&&1\quad&&1/3\\ &8\quad&&3\quad&&1\\ \end{aligned}\right]\\ B_3=\left [ \begin{aligned} &1\quad&&1\quad&&3\\ &1\quad&&1\quad&&3\\ &1/3\quad&&1/3\quad&&1\\ \end{aligned}\right] B_4=\left [ \begin{aligned} &1\quad&&3\quad&&4\\ &1/3\quad&&1\quad&&1\\ &1/4\quad&&1\quad&&1\\ \end{aligned}\right] B_5=\left [ \begin{aligned} &1\quad&&1\quad&&1/4\\ &1\quad&&1\quad&&1/4\\ &4\quad&&4\quad&&1\\ \end{aligned}\right]\\
那么我们就可以给出如下的代码:
import numpy as np
#RI标准值
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59]
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#计算最大特征向量
def calEigVec(self):
k=[i for i in range(len(self.V)) if self.V[i] == np.max(self.V)]
return -self.D[:,k]
#分配权向量
def giveWeight(self):
weight_vec=np.zeros((self.n,1))
for i in range(0,self.n):
weight_vec[i]=self.eig_vec[i]/np.sum(self.eig_vec)
return weight_vec
#检验一致性
def checkConsistency(self):
if self.CR>=0.1:
return False
else:
return True
def __init__(self,elem):
self.elem=elem #元素
self.n=self.elem.shape[1] #阶数
self.V=np.linalg.eig(self.elem)[0] #特征值
self.D=np.linalg.eig(self.elem)[1] #特征向量
self.eig_val=np.max(self.V) #最大特征值
self.eig_vec=self.calEigVec() #最大特征向量
self.W=self.giveWeight() #权向量
self.CI=(self.eig_val-self.n)/(self.n-1) #一致性指标
self.RI=RI[self.n-1] #采用的随机一致性指标
self.CR=self.CI/self.RI #一致性比率
self.accepted=self.checkConsistency() #是否通过一致性检验
def __str__(self):
s1=f'elem=\n{self.elem}\n'
s2=f'n={self.n}\n'
s3=f'V=\n{self.V}\n'
s4=f'D=\n{self.D}\n'
s5=f'eig_val={self.eig_val}\n'
s6=f'eig.vec=\n{self.eig_vec}\n'
s7=f'W=\n{self.W}\n'
s8=f'CI={self.CI}\n'
s9=f'RI={self.RI}\n'
s10=f'CR={self.CR}\n'
s11=f'accepted={self.accepted}'
return(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11)
#构造矩阵
A_e=np.array([[1,1/2,4,3,3],
[2,1,7,5,5],
[1/4,1/7,1,1/2,1/3],
[1/3,1/5,2,1,1],
[1/3,1/5,3,1,1]])
B1_e=np.array([[1,2,5],[1/2,1,2],[1/5,1/2,1]])
B2_e=np.array([[1,1/3,1/8],[3,1,1/3],[8,3,1]])
B3_e=np.array([[1,1,3],[1,1,3],[1/3,1/3,1]])
B4_e=np.array([[1,3,4],[1/3,1,1],[1/4,1,1]])
B5_e=np.array([[1,1,1/4],[1,1,1/4],[4,4,1]])
A=PairwiseComparisonMatrix(A_e)
B_e=[B1_e,B2_e,B3_e,B4_e,B5_e]
B=[]
for Bi_e in B_e:
B.append(PairwiseComparisonMatrix(Bi_e))
#层次总排序一致性检验
CIs=np.array([B[0].CI,B[1].CI,B[2].CI,B[3].CI,B[4].CI])
CR=sum(np.squeeze(A.W.T)*CIs)/RI[3-1]
print(f'CR={CR}')
if CR>=0.1:
print('没有通过一致性检验\n')
else:
print('通过一致性检验\n')
#计算权向量
P1=np.array([np.squeeze(B[0].W.T)[0],np.squeeze(B[1].W.T)[0],np.squeeze(B[2].W.T)[0],np.squeeze(B[3].W.T)[0],np.squeeze(B[4].W.T)[0]])
P2=np.array([np.squeeze(B[0].W.T)[1],np.squeeze(B[1].W.T)[1],np.squeeze(B[2].W.T)[1],np.squeeze(B[3].W.T)[1],np.squeeze(B[4].W.T)[1]])
P3=np.array([np.squeeze(B[0].W.T)[2],np.squeeze(B[1].W.T)[2],np.squeeze(B[2].W.T)[2],np.squeeze(B[3].W.T)[2],np.squeeze(B[4].W.T)[2]])
weight_P1=sum(np.squeeze(A.W.T)*P1) #苏杭权重
weight_P2=sum(np.squeeze(A.W.T)*P2) #北戴河权重
weight_P3=sum(np.squeeze(A.W.T)*P3) #桂林权重
weights=np.array([weight_P1,weight_P2,weight_P3]) #决策向量
CR=(0.0026682144913118106+0j) 通过一致性检验
总结
综合以上几步,我们对于选择旅游目的地的解决方法如下:
首先,建立如图所示的模型
其次,构造矩阵如下:
A=\left [ \begin{aligned} &1\quad&&1/2\quad&&4\quad&&3\quad&&3\\ &2\quad&&1\quad&&7\quad&&5\quad&&5\\ &1/4\quad&&1/7\quad&&1\quad&&1/2\quad&&1/3\\ &1/3\quad&&1/5\quad&&2\quad&&1\quad&&1\\ &1/3\quad&&1/5\quad&&3\quad&&1\quad&&1\\ \end{aligned}\right]
B_1=\left [ \begin{aligned} &1\quad&&2\quad&&5\\ &1/2\quad&&1\quad&&2\\ &1/5\quad&&1/2\quad&&1\\ \end{aligned}\right] B_2=\left [ \begin{aligned} &1\quad&&1/3\quad&&1/8\\ &3\quad&&1\quad&&1/3\\ &8\quad&&3\quad&&1\\ \end{aligned}\right]\\ B_3=\left [ \begin{aligned} &1\quad&&1\quad&&3\\ &1\quad&&1\quad&&3\\ &1/3\quad&&1/3\quad&&1\\ \end{aligned}\right] B_4=\left [ \begin{aligned} &1\quad&&3\quad&&4\\ &1/3\quad&&1\quad&&1\\ &1/4\quad&&1\quad&&1\\ \end{aligned}\right] B_5=\left [ \begin{aligned} &1\quad&&1\quad&&1/4\\ &1\quad&&1\quad&&1/4\\ &4\quad&&4\quad&&1\\ \end{aligned}\right]\\
最后,将数据导入程序:
import numpy as np
import sys
#代入数据
A_e=np.array([[1,1/2,4,3,3],
[2,1,7,5,5],
[1/4,1/7,1,1/2,1/3],
[1/3,1/5,2,1,1],
[1/3,1/5,3,1,1]])
B1_e=np.array([[1,2,5],[1/2,1,2],[1/5,1/2,1]])
B2_e=np.array([[1,1/3,1/8],[3,1,1/3],[8,3,1]])
B3_e=np.array([[1,1,3],[1,1,3],[1/3,1/3,1]])
B4_e=np.array([[1,3,4],[1/3,1,1],[1/4,1,1]])
B5_e=np.array([[1,1,1/4],[1,1,1/4],[4,4,1]])
#RI标准值
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59]
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#计算最大特征向量
def calEigVec(self):
k=[i for i in range(len(self.V)) if self.V[i] == np.max(self.V)]
return -self.D[:,k]
#分配权向量
def giveWeight(self):
weight_vec=np.zeros((self.n,1))
for i in range(0,self.n):
weight_vec[i]=self.eig_vec[i]/np.sum(self.eig_vec)
return weight_vec
#检验一致性
def checkConsistency(self):
if self.CR>=0.1:
return False
else:
return True
def __init__(self,elem):
self.elem=elem #元素
self.n=self.elem.shape[1] #阶数
self.V=np.linalg.eig(self.elem)[0] #特征值
self.D=np.linalg.eig(self.elem)[1] #特征向量
self.eig_val=np.max(self.V) #最大特征值
self.eig_vec=self.calEigVec() #最大特征向量
self.W=self.giveWeight() #权向量
self.CI=(self.eig_val-self.n)/(self.n-1) #一致性指标
self.RI=RI[self.n-1] #采用的随机一致性指标
self.CR=self.CI/self.RI #一致性比率
self.accepted=self.checkConsistency() #是否通过一致性检验
def __str__(self):
s1=f'elem=\n{self.elem}\n'
s2=f'n={self.n}\n'
s3=f'V=\n{self.V}\n'
s4=f'D=\n{self.D}\n'
s5=f'eig_val={self.eig_val}\n'
s6=f'eig.vec=\n{self.eig_vec}\n'
s7=f'W=\n{self.W}\n'
s8=f'CI={self.CI}\n'
s9=f'RI={self.RI}\n'
s10=f'CR={self.CR}\n'
s11=f'accepted={self.accepted}'
return(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11)
#构造矩阵
A=PairwiseComparisonMatrix(A_e)
B_e=[B1_e,B2_e,B3_e,B4_e,B5_e]
B=[]
for Bi_e in B_e:
B.append(PairwiseComparisonMatrix(Bi_e))
#层次单排序一致性检验
for i in range(0,len(B)):
if B[i].accepted==False:
print(f'B[{i}]数据层次单排序一致性检验不通过,请调整数据!')
sys.exit(0)
#层次总排序一致性检验
CIs=np.array([B[0].CI,B[1].CI,B[2].CI,B[3].CI,B[4].CI])
CR=sum(np.squeeze(A.W.T)*CIs)/RI[3-1]
#计算权向量
P1=np.array([np.squeeze(B[0].W.T)[0],np.squeeze(B[1].W.T)[0],np.squeeze(B[2].W.T)[0],np.squeeze(B[3].W.T)[0],np.squeeze(B[4].W.T)[0]])
P2=np.array([np.squeeze(B[0].W.T)[1],np.squeeze(B[1].W.T)[1],np.squeeze(B[2].W.T)[1],np.squeeze(B[3].W.T)[1],np.squeeze(B[4].W.T)[1]])
P3=np.array([np.squeeze(B[0].W.T)[2],np.squeeze(B[1].W.T)[2],np.squeeze(B[2].W.T)[2],np.squeeze(B[3].W.T)[2],np.squeeze(B[4].W.T)[2]])
weight_P1=sum(np.squeeze(A.W.T)*P1) #苏杭权重
weight_P2=sum(np.squeeze(A.W.T)*P2) #北戴河权重
weight_P3=sum(np.squeeze(A.W.T)*P3) #桂林权重
weights=np.array([weight_P1,weight_P2,weight_P3]) #决策向量
#进行决策
if CR>=0.1:
print("层次总排序数据一致性检验不通过,请重新调整数据!")
for i,weight in enumerate(weights):
print(f"目标{i+1}的权重得分为:{weight}")
print(f'目标{np.argmax(weights)+1}的权重得分最高,为{max(weights)},建议选择目标{np.argmax(weights)+1}')
#得出结论,目的地三,即去桂林
目标1的权重得分为:0.2992545297453049 目标2的权重得分为:0.24530398001537007 目标3的权重得分为:0.45544149023932495 目标3的权重得分最高,为0.45544149023932495,建议选择目标3
层次规划综合实战:选拔优秀参赛队员问题
问题提出
设某学校数学建模教练组根据实际需要,拟从报名参赛的20名队员中选出15名优秀队员代表学生参赛。表1给出了20名队员的基本条件的量化情况。
请根据这些条件对20名队员进行综合评价,从中选出15名综合素质较高的优秀队员。
队员i | 学科知识竞赛成绩r_i^{(1)} | 思维敏捷度r_i^{(2)} | 知识面宽广度r_i^{(3)} | 写作能力r_i^{(4)} | 计算机应用能力r_i^{(5)} | 团结协作能力r_i^{(6)} |
1 | 86 | 9.0 | 8.2 | 8.0 | 7.9 | 9.5 |
2 | 82 | 8.8 | 8.1 | 6.5 | 7.7 | 9.1 |
3 | 80 | 8.6 | 8.5 | 8.5 | 9.2 | 9.6 |
4 | 85 | 8.9 | 8.3 | 9.6 | 9.7 | 9.7 |
5 | 88 | 8.4 | 8.5 | 7.7 | 8.6 | 9.2 |
6 | 92 | 9.2 | 8.2 | 7.9 | 9.0 | 9.0 |
7 | 92 | 9.6 | 9.0 | 7.2 | 9.1 | 9.2 |
8 | 92 | 8.0 | 9.8 | 6.2 | 8.7 | 9.7 |
9 | 70 | 8.2 | 8.2 | 8.4 | 6.5 | 9.6 |
10 | 77 | 8.1 | 8.6 | 6.9 | 8.5 | 9.4 |
11 | 83 | 8.0 | 8.0 | 7.8 | 9.0 | 9.2 |
12 | 90 | 9.7 | 8.1 | 9.9 | 8.7 | 9.5 |
13 | 96 | 9.6 | 8.3 | 8.1 | 9.0 | 9.7 |
14 | 95 | 8.3 | 8.8 | 8.1 | 8.8 | 9.3 |
15 | 86 | 8.2 | 8.2 | 8.4 | 8.6 | 9.0 |
16 | 91 | 8.0 | 8.6 | 8.8 | 8.4 | 9.4 |
17 | 93 | 8.7 | 9.4 | 9.2 | 8.7 | 9.5 |
18 | 84 | 8.4 | 9.2 | 9.1 | 7.8 | 9.1 |
19 | 87 | 8.3 | 9.5 | 7.9 | 9.0 | 9.6 |
20 | 78 | 8.1 | 9.6 | 7.6 | 9.0 | 9.2 |
问题的分析与假设
问题分析
这是一个半定性与半定量、多因素的综合选优排序问题。鉴于数学建模竞赛不仅要考查学生的学科知识、还要考查学生的写作能力、计算机应用能力、团结协助能力等多方面的因素,要从20名队员中选拔出优秀参赛队员,就要对表1中所列的六个因素进行比较分析,综合排序选优。
模型假设
(1)题目中所确定的考评条件是合理的,能够反映出参选队员的建模能力;
(2)各参选队员的量化得分是按统一的量化标准得出的;
(3)对参选队员的量化打分是公平的,所有参选队员对打分结果无异议;
(4)选拔队员所考虑的六个因素在选拔优秀队员中所起的作用依次为学科知识竞赛成绩、思维敏捷度、知识面宽广度、写作能力、计算机应用能力、团结协助能力,并且相邻两个因素的影响程度之差基本相同。
建立数据表格
存储表1数据的excel文件位于和python同一目录的data.xlsx文件下,具体的读取操作解析可以参考以下笔记:
模型的建立与求解
建立层次结构图
建立如下图所示的层次结构图:
第一层为目标层:选拔优秀参赛队员;
第二层为准则层:选拔优秀队员时所考虑的6个因素,依次为学科知识竞赛成绩、思维敏捷度、知识面宽广度、写作能力、计算机应用能力、协助能力;
第三层为方案层:参选的20名队员。
确定准则层对目标层的权重向量
根据假设,构造准则层C对目标层的成对比较矩阵
A=\left [ \begin{aligned} &1\quad&&2\quad&&3\quad&&4\quad&&5\quad&&6\\ &1/2\quad&&1\quad&&2\quad&&3\quad&&4\quad&&5\\ &1/3\quad&&1/2\quad&&1\quad&&2\quad&&3\quad&&4\\ &1/4\quad&&1/3\quad&&1/2\quad&&1\quad&&2\quad&&3\\ &1/5\quad&&1/4\quad&&1/3\quad&&1/2\quad&&1\quad&&2\\ &1/6\quad&&1/5\quad&&1/4\quad&&1/3\quad&&1/2\quad&&1\\ \end{aligned}\right]
用python来获得这个矩阵的各项数据:
import numpy as np
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#(此处已多次提及,故不再重复,省略)
#构造矩阵
A_e=np.array([[1,2,3,4,5,6],
[1/2,1,2,3,4,5],
[1/3,1/2,1,2,3,4],
[1/4,1/3,1/2,1,2,3],
[1/5,1/4,1/3,1/2,1,2],
[1/6,1/5,1/4,1/3,1/2,1]])
A=PairwiseComparisonMatrix(A_e)
print(A)
elem= [[1. 2. 3. 4. 5. 6. ] [0.5 1. 2. 3. 4. 5. ] [0.33333333 0.5 1. 2. 3. 4. ] [0.25 0.33333333 0.5 1. 2. 3. ] [0.2 0.25 0.33333333 0.5 1. 2. ] [0.16666667 0.2 0.25 0.33333333 0.5 1. ]] n=6 V= [ 6.12246363+0.j 0.01615141+0.85346982j 0.01615141-0.85346982j -0.05935603+0.13529106j -0.05935603-0.13529106j -0.03605438+0.j ] D= [[-0.76417539+0.j -0.82369558+0.j -0.82369558-0.j 0.70962122+0.j 0.70962122-0.j 0.61946226+0.j ] [-0.50026698+0.j -0.24773754-0.35888748j -0.24773754+0.35888748j -0.29165652+0.42455723j -0.29165652-0.42455723j -0.56801757+0.j ] [-0.31881861+0.j 0.10921225-0.25507943j 0.10921225+0.25507943j -0.22383225-0.2904272j -0.22383225+0.2904272j 0.3946258 +0.j ] [-0.20104497+0.j 0.17451951-0.04358871j 0.17451951+0.04358871j 0.22900298-0.06560719j 0.22900298+0.06560719j -0.29566612+0.j ] [-0.1280175 +0.j 0.08135636+0.07636738j 0.08135636-0.07636738j -0.00896374+0.17224539j -0.00896374-0.17224539j 0.20605182+0.j ] [-0.08553391+0.j -0.02110497+0.09542198j -0.02110497-0.09542198j -0.06135416-0.08010428j -0.06135416+0.08010428j -0.08953891+0.j ]] eig_val=(6.122463628004883+0j) eig.vec= [[0.76417539-0.j] [0.50026698-0.j] [0.31881861-0.j] [0.20104497-0.j] [0.1280175 -0.j] [0.08553391-0.j]] W= [[0.38249747] [0.25040175] [0.15958026] [0.10063029] [0.0640774 ] [0.04281282]] CI=(0.024492725600976685+0j) RI=1.24 CR=(0.01975219806530378+0j) accepted=True
其中比较重要的数据有:
准则层对目标层的权重向量W= [[0.38249747] [0.25040175] [0.15958026] [0.10063029] [0.0640774 ] [0.04281282]]
CR=(0.01975219806530378+0j)<0.1,通过一致性检验
确定方案层对准则层的权重向量
根据表1和模型假设,构造方案层P中20个队员对准则层C中各因素C_k的成对比较矩阵:
B_k=(b_{ij}^{(k)})_{20 \times 20},其中b_{ij}^{(k)}=\frac{r_i^{(k)}}{r_j^{(k)}},(i,j=1,2,...,20,k=1,2,...,6)
显然,所有的B_k均为一致阵,于是B_k的最大特征根为:
λ_{\max}^{(k)}=20,CI_k=0,CR_k=0
在python里实现以上步骤:
import pandas as pd
import numpy as np
import sys
#RI标准值
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59,1.5943,1.6064,1.6133,1.6207,1.6292]
#数据导入
A_e=np.array([[1,2,3,4,5,6],
[1/2,1,2,3,4,5],
[1/3,1/2,1,2,3,4],
[1/4,1/3,1/2,1,2,3],
[1/5,1/4,1/3,1/2,1,2],
[1/6,1/5,1/4,1/3,1/2,1]])
B_e=[]
for i in range(1,6):
B_e.append(np.zeros((20,20)))
data=pd.read_excel(r'data.xlsx',index_col=0)
r=np.array(data)
for k in range(0,len(B_e)):
for i in range(0,B_e[k].shape[0]):
for j in range(0,B_e[k].shape[1]):
B_e[k][i][j]=r[i][k]/r[j][k]
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#(此处已多次提及,故不再重复,省略)
#构造矩阵
A=PairwiseComparisonMatrix(A_e)
B=[]
for Bi_e in B_e:
B.append(PairwiseComparisonMatrix(Bi_e))
#检验层次单排序一致性
print("\n层次单排序检验结果:\n")
if A.accepted==False:
print(f'A层次单排序检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print(f'A层次单排序检验通过!')
for Bi in B:
if Bi.accepted==False:
print(f'B[{B.index(Bi)}]层次单排序检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print(f'B[{B.index(Bi)}]层次单排序检验通过!')
print("\n层次单排序检验全部通过!\n")
print(f'B_k的最大特征根为:{max([Bi.eig_val for Bi in B])}')
print(f'CI_k={max([Bi.CI for Bi in B])}')
print(f'CR_k={max([Bi.CR for Bi in B])}')
层次单排序检验结果: A层次单排序检验通过! B[0]层次单排序检验通过! B[1]层次单排序检验通过! B[2]层次单排序检验通过! B[3]层次单排序检验通过! B[4]层次单排序检验通过! 层次单排序检验全部通过! B_k的最大特征根为:(20.000000000000007+0j) CI_k=(3.739698609263685e-16+0j) CR_k=(2.2954202119222226e-16+0j)
确定方案层对准则层的权重向量
B_k的任一列向量都是λ_{\max}的特征向量,将其归一化得到方案层P对C_k的权重向量ω_k^{(3)}。于是,方案层对准则层的权重向量矩阵为:
W^{(3)}=[ω_1^{(3)},ω_2^{(3)},...,ω_6^{(3)}]_{20 \times 6}
一致性比率为CR_k=0(k=1,2,…,6),通过一致性检验。
在python里实现以上步骤:
#………………………………
#前部代码重复,省略
#确定方案层对准则层的权重向量
C=np.squeeze(np.array([B[0].W,B[1].W,B[2].W,B[3].W,B[4].W,B[5].W])).T
#层次总排序一致性检验
print("\n层次总排序一致性检验结果:\n")
CIs=np.array([B[0].CI,B[1].CI,B[2].CI,B[3].CI,B[4].CI,B[5].CI])
CR=sum(np.squeeze(A.W.T)*CIs)/RI[15-1]
print(f'CR_k={CR}\n')
if CR>=0.1:
print('层次总排序一致性检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print("层次总排序一致性检验通过!\n")
层次总排序一致性检验结果: CR_k=(2.4183482960599863e-18+0j) 层次总排序一致性检验通过!
确定方案层P对目标层O的组合权重向量
方案层对目标层的组合权重向量为:
ω^{(3)}=W^{(3)}ω^{(2)}= (0.0498,0.0474,0.0490,0.0513, 0.0497,0.0517,0.0526,0.0504, 0.0450,0.0464,0.0480,0.0523, 0.0535,0.0511,0.0496,0.0505, 0.0531,0.0500,0.0506,0.0481)^T组合一致性指标CI^{(3)}=0,组合一致性比率为:
CR^{(3)}=CR^{(2)}+\frac{CI^{(3)}}{RI^{(3)}}=0.0198<0.1
通过一致性检验,组合权重ω^{(3)}可以作为决策依据
用python完成以上步骤:
#………………………………
#前部代码重复,省略
#确定方案层P对目标层O的组合权重向量
#数学公式为ω^(3)=W^(3)*ω^(2),用程序中的变量等价代换为:W=np.matmul(C,A.W)
W=np.matmul(C,A.W)
print(W)
#检验第三层层次总排序一致性
print("\n第三层层次总排序一致性检验结果:\n")
CR=A.CR+sum(np.squeeze(A.W.T)*CIs)/RI[15-1]
print(f'CR={CR}\n')
if CR>=0.1:
print('第三层层次总排序一致性检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print("第三层层次总排序一致性检验通过!\n")
[[0.04979123] [0.04742333] [0.04897532] [0.05122819] [0.04964363] [0.05164479] [0.05261188] [0.05036455] [0.0448333 ] [0.04637387] [0.04770458] [0.05308335] [0.05348912] [0.05167123] [0.04902279] [0.05047352] [0.05305592] [0.04995271] [0.05056337] [0.04809332]] 第三层层次总排序一致性检验结果: CR=(0.019752198065303737+0j) 第三层层次总排序一致性检验通过!
将权重ω^{(3)}的20个分量分别作为20个队员的综合实力,从小到大依次为[ 9 10 2 11 20 3 15 5 1 18 8 16 19 4 6 14 7 17 12 13],于是淘汰最后五位:[ 9 10 2 11 20]
#………………………………
#前部代码重复,省略
#进行决策
W=np.squeeze(W.T)
print(f'目标权重排序为:{W.argsort()+1}')
print(f'选中目标:{W.argsort()[-15:]+1}')
print(f'落选目标:{W.argsort()[:5]+1}')
目标权重排序为:[ 9 10 2 11 20 3 15 5 1 18 8 16 19 4 6 14 7 17 12 13] 选中目标:[ 3 15 5 1 18 8 16 19 4 6 14 7 17 12 13] 落选目标:[ 9 10 2 11 20]
完整代码
完整代码展示如下:
import pandas as pd
import numpy as np
import sys
#RI标准值
RI=[0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49,1.52,1.54,1.56,1.58,1.59,1.5943,1.6064,1.6133,1.6207,1.6292]
#数据导入
A_e=np.array([[1,2,3,4,5,6],
[1/2,1,2,3,4,5],
[1/3,1/2,1,2,3,4],
[1/4,1/3,1/2,1,2,3],
[1/5,1/4,1/3,1/2,1,2],
[1/6,1/5,1/4,1/3,1/2,1]])
B_e=[]
for i in range(0,6):
B_e.append(np.zeros((20,20)))
data=pd.read_excel(r'data.xlsx',index_col=0)
r=np.array(data)
for k in range(0,len(B_e)):
for i in range(0,B_e[k].shape[0]):
for j in range(0,B_e[k].shape[1]):
B_e[k][i][j]=r[i][k]/r[j][k]
#构造成对比较矩阵类
class PairwiseComparisonMatrix:
#计算最大特征向量
def calEigVec(self):
k=[i for i in range(len(self.V)) if self.V[i] == np.max(self.V)]
return -self.D[:,k]
#分配权向量
def giveWeight(self):
weight_vec=np.zeros((self.n,1))
for i in range(0,self.n):
weight_vec[i]=self.eig_vec[i]/np.sum(self.eig_vec)
return weight_vec
#检验一致性
def checkConsistency(self):
if self.CR>=0.1:
return False
else:
return True
def __init__(self,elem):
self.elem=elem #元素
self.n=self.elem.shape[1] #阶数
self.V=np.linalg.eig(self.elem)[0] #特征值
self.D=np.linalg.eig(self.elem)[1] #特征向量
self.eig_val=np.max(self.V) #最大特征值
self.eig_vec=self.calEigVec() #最大特征向量
self.W=self.giveWeight() #权向量
self.CI=(self.eig_val-self.n)/(self.n-1) #一致性指标
self.RI=RI[self.n-1] #采用的随机一致性指标
self.CR=self.CI/self.RI #一致性比率
self.accepted=self.checkConsistency() #是否通过一致性检验
def __str__(self):
s1=f'elem=\n{self.elem}\n'
s2=f'n={self.n}\n'
s3=f'V=\n{self.V}\n'
s4=f'D=\n{self.D}\n'
s5=f'eig_val={self.eig_val}\n'
s6=f'eig.vec=\n{self.eig_vec}\n'
s7=f'W=\n{self.W}\n'
s8=f'CI={self.CI}\n'
s9=f'RI={self.RI}\n'
s10=f'CR={self.CR}\n'
s11=f'accepted={self.accepted}'
return(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11)
#构造矩阵
A=PairwiseComparisonMatrix(A_e)
B=[] #对应关系:B_k==B[k-1]
for Bi_e in B_e:
B.append(PairwiseComparisonMatrix(Bi_e))
#检验第二层层次单排序一致性
print("\n第二层层次单排序一致性检验结果:\n")
if A.accepted==False:
print(f'A层次单排序检验不通过,请检查数据并重试!')
sys.exit(0)
for Bi in B:
if Bi.accepted==False:
print(f'B[{B.index(Bi)}]层次单排序检验不通过,请检查数据并重试!')
sys.exit(0)
print(f'B_k的最大特征根为:{max([Bi.eig_val for Bi in B])}')
print(f'CI_k={max([Bi.CI for Bi in B])}')
print(f'CR_k={max([Bi.CR for Bi in B])}\n')
print("第二层层次单排序一致性检验全部通过!\n")
#确定方案层对准则层的权重向量
#C即公式中的W^(3)
C=np.squeeze(np.array([B[0].W,B[1].W,B[2].W,B[3].W,B[4].W,B[5].W])).T
#检验第二层层次总排序一致性
print("\n第二层层次总排序一致性检验结果:\n")
CIs=np.array([B[0].CI,B[1].CI,B[2].CI,B[3].CI,B[4].CI,B[5].CI])
CR=sum(np.squeeze(A.W.T)*CIs)/RI[15-1]
print(f'CR_k={CR}\n')
if CR>=0.1:
print('第二层层次总排序一致性检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print("第二层层次总排序一致性检验通过!\n")
#确定方案层P对目标层O的组合权重向量
#数学公式为ω^(3)=W^(3)*ω^(2),用程序中的变量等价代换为:W=np.matmul(C,A.W)
W=np.matmul(C,A.W)
#检验第三层层次总排序一致性
print("\n第三层层次总排序一致性检验结果:\n")
CR=A.CR+sum(np.squeeze(A.W.T)*CIs)/RI[15-1]
print(f'CR={CR}\n')
if CR>=0.1:
print('第三层层次总排序一致性检验不通过,请检查数据并重试!')
sys.exit(0)
else:
print("第三层层次总排序一致性检验通过!\n")
#进行决策
W=np.squeeze(W.T)
print(f'目标权重排序为:{W.argsort()+1}')
print(f'选中目标:{W.argsort()[-15:]+1}')
print(f'落选目标:{W.argsort()[:5]+1}')
第二层层次单排序一致性检验结果: B_k的最大特征根为:(20.000000000000007+0j) CI_k=(3.739698609263685e-16+0j) CR_k=(2.2954202119222226e-16+0j) 第二层层次单排序一致性检验全部通过! 第二层层次总排序一致性检验结果: CR_k=(-4.2563578307411553e-17+0j) 第二层层次总排序一致性检验通过! 第三层层次总排序一致性检验结果: CR=(0.019752198065303737+0j) 第三层层次总排序一致性检验通过! 目标权重排序为:[ 9 10 2 11 20 3 15 5 1 18 8 16 19 4 6 14 7 17 12 13] 选中目标:[ 3 15 5 1 18 8 16 19 4 6 14 7 17 12 13] 落选目标:[ 9 10 2 11 20]
模型的结果分析与推广
(1)由表1,20名队员六项条件互有强弱,利用层次分析法得到了一种合理的综合排序方案,结果选出了综合实力较强的15名队员
第13号队员各项条件总体较强,排在了第一位;
第9号和第10号队员各项条件总体较弱,排在后两位;
(2)该模型还可以应用到三好学生的评选问题、旅游景点的选择问题、综合实力的评价分析问题等
层次分析法的几点说明
层次分析法的优点
系统性
把所研究的问题看成一个系统,按照分解、比较判断、综合分析的思维方式进行决策分析,也是实际中继机理分析方法、统计分析方法之后发展起来的又一个重要的系统分析工具
实用性
把定性与定量方法结合起来,能处理许多传统的优化方法无法处理的实际问题,应用范围广。而且将决策者和决策分析者联系起来,体现了决策者的主观意见,决策者可以直接应用它进行决策分析,增加了决策的有效性和实用性
简洁性
具有中等文化程度的人都可以学习掌握层次分析法的基本原理和步骤,计算也比较简便,所得结果简单明确,容易被决策者了解和掌握
层次分析法的局限性
局限性是粗略、主观.首先是它的比较、判断及结果都是粗糙的,不适于精度要求很高的问题;
其次是从建立层次结构图到给出两两比较矩阵,人的主观因素作用很大,使决策结果较大程度地依赖于决策人的主观意志,可能难以为众人所接受。
更新补丁v230122
考虑到手输成对比较矩阵会产生一次重复计算,所以设计了一个函数。使用者只需要给出一个上三角矩阵,函数将自动填充下三角部分。
请注意:该矩阵的数据类型必须为浮点数float,否则可能不会完成目标
import numpy as np
#数据自动配对函数
def autoPair(matrix):
res=matrix
for i in range(0,res.shape[0]):
for j in range(0,i):
res[i,j]=1/res[j,i]
return res
a=np.array([[1,2,3,4,5,6],
[0,1,2,3,4,5],
[0,0,1,2,3,4],
[0,0,0,1,2,3],
[0,0,0,0,1,2],
[0,0,0,0,0,1]],dtype=float)
a=autoPair(a)
print(a)
[[1. 2. 3. 4. 5. 6. ] [0.5 1. 2. 3. 4. 5. ] [0.33333333 0.5 1. 2. 3. 4. ] [0.25 0.33333333 0.5 1. 2. 3. ] [0.2 0.25 0.33333333 0.5 1. 2. ] [0.16666667 0.2 0.25 0.33333333 0.5 1. ]]