数学建模导论之层次分析法(Datawhale开源学习)

【教程地址】:

数学建模导论

 https://datawhalechina.github.io/intro-mathmodel/#/

搭配以下内容食用效果更佳:

Python科学计算
 https://datawhalechina.github.io/scientific-computing/#/

7.1 层次分析法

7.1.1 层次分析法原理

基本步骤:

     1.选择指标,建立递阶层次结构模型

选择指标。在面对评价类问题,选择指标往往需要依据文献研究或社会调查来确定。若缺少明确指标,可通过发放问卷、运用德尔菲法等手段,结合专家意见来构建评价准则。

构造层次模型图。从结构上看,层次分析法将模型大致分为目标层、准则层和方案层。目标层是评价目标,准则层是评价指标体系,方案层是多个对比方案。

      2.对目标层到准则层之间和准则层到方案层之间构造判断矩阵

对指标重要性重要性进行两两比较,构造判断矩阵。两个相邻的层次之间是需要构建成对比较矩阵的。矩阵元素 aij 意义:第 i 个指标对第 j 个指标的重要程度。

表中描述的重要性是因素 i 比因素 j 重要的情况下描述的。如果是因素 j 比因素 i 重要,由表中得到的“相对不重要程度”那就用 1~9 的倒数描述即可。

注意:通常来说,对重要性的取值都是取奇数,也就是 1、3、5、7、9,偶数是当不太确定,即认为介于两个奇数程度之间时再取偶数。

在目标层和准则层之间就需要构建第一层比较矩阵。除了准则层外,方案层也需要构建成对比较矩阵。但不同的是,假如有 m 个准则 n 个样本,需要构建的矩阵数量为 m,矩阵大小为(n,n)。每个成对比较矩阵是需要我们自己手动确定的。

       3.层次单排序和一致性检验

在层次分析法中构建的判断矩阵是正互反矩阵,方阵中每个元系满足:

a_{ij}>0       a_{ij} *a_{ji}=1

若同时,正互反矩阵也满足:

a_{ik} *a_{kj}=a_{ij}

则称其为一致矩阵。

目的:确定构建的判断矩阵是否存在逻辑问题。

原理:检验构子的判断矩阵和一致矩阵是否有太大差别。

步骤:

     4.计算权重向量

进行权重计算之前要先对判断矩阵进行一致性检验。

权重的计算有三种方法:

①算数平均法求权重

②几何平均法求权重

③特征值法求权重

求出矩阵A的最大特征值以及其对应的特征向量,对求出的特征向量进行归一化即可得到权重。

      5.层次总排序和一致性检验

计算某一层次所有因素对于最高层(目标层)相对重要性的权值,称为层次总排序。该过程是从最高层次向最低层次依次进行的。

设上一层次(A层)包含A1,...,Am共m个因素,它们的层次总排序权重分别为 a1,...,am。又设其后的下一层次(B层)包含n个因素B1,...,Bn,它们关于Aj的层次单排序权重分别为b1j,...,bnj。

对层次总排序也需作一致性检验,检验仍像层次总排序那样由高层到低层逐层进行。这是因为当综合考察时,各层次的非一致性仍有可能积累起来, 引起最终分析结果较严重的非一致性。

     6.求权重后进行评价

根据权重和方案的评分进行综合评价。

7.1.2 层次分析法案例

为了更好地理解层次分析法的应用,我们来看一个具体的案例——水质评价。

例 7.1 某日从三条河流的基站处抽检水样,得到了水质的四项检测指标如表 5.1 所示。请根据提供数据对三条河流的水质进行评价。其中,DO 代表水中溶解氧含量,越大越好;CODMn 表示水中高锰酸盐指数,NH3-N 表示氨氮含量,这两项指标越小越好;pH 值没有量纲,在 6~9 区间内较为合适。

例 7.1数据

地点名称pH*DOCODMnNH3-N
四川攀枝花龙洞7.949.471.630.077
重庆朱沱8.1591.40.417
湖北宜昌南津关8.068.452.830.203

首先,构建一个层次结构模型。该评价问题一共有三个样本,四个评价指标,根据所给评价指标,构建层次模型图:

接下来,需对准则层的各因素进行成对比较,构建成对比较矩阵。对目标层到准则层构建一个大小为 4 的方阵,准则层到方案层构建 4 个大小为 3 的方阵。例如:

变量pH*DOCODMnNH3-N
pH*1.001/51/31
DO5.00135
CODMn3.001/313
NH3-N1.001/51/31

通过特征值分解的方法,计算出成对比较矩阵的最大特征值和对应的特征向量,进而得到权重向量,代码如下:

import numpy as np 

# 构建矩阵
A=np.array([[1,1/5,1/3,1],[5,1,3,5],[3,1/3,1,3],[1,1/5,1/3,1]])#获得指标个数
m=len(A)
n=len(A[0])
RI=[0,0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45,1.49,1.51]#求判断矩阵的特征值和特征向量,V为特征值,D为特征向量
V,D=np.linalg.eig(A)
list1=list(V)#求矩阵的最大特征值
B=np.max(list1)
index=list1.index(B)
C=D[:,index]

计算一致性指标(CI)和一致性比率(CR),检验成对比较矩阵的一致性。

CI=(B-n)/(n-1)
CR=CI/RI[n]
if CR<0.10:
    print("CI=",CI)
    print("CR=",CR)
    print("对比矩阵A通过一致性检验,各向量权重向量Q为:")
    C_sum=np.sum(C)
    Q=C/C_sum
    print(Q)
else:
    print("对比矩阵A未通过一致性检验,需对对比矩阵A重新构造")

结果输出如下:

CI= (0.014497820535966117+0j)
CR= (0.0161086894844068+0j)
对比矩阵A通过一致性检验,各向量权重向量Q为:
[0.09546368-0.j 0.55958606-0.j 0.24948658-0.j 0.09546368-0.j]

分解出来的权重向量为什么是个复数?python 进行矩阵分解的时候是在复数域内进行分解,所得到的向量也是复数向量。虚部为 0 的情况下想要单独分析实部,通过 Q.real 即可达成取实部的效果。

计算出目标层到准则层的 1 个权重向量和 4 个准则层到方案层的权重向量以后,可以列出下表将权重向量进行排布。

例 7.1 中 4 个权重向量的排布

地点名称pH*DOCODMnNH3-N得分
0.09550.55960.24950.0955
四川攀枝花龙洞0.41660.53960.2970.6370.4767
重庆朱沱0.32750.2970.53960.10470.3421
湖北宜昌南津关0.25990.16340.16340.25830.1817

将准则层到方案层得到的 7 个成对比较矩阵对应的权重向量排列为一个矩阵,矩阵的每一行表示对应的方案,矩阵的每一列代表评价准则。将这一方案权重矩阵与目标层到准则层的权重向量进行数量积,得到的分数就是最终的评分。最终得到的一个结论是:在评价过程中水中溶解氧含量与钴金属含量占评价体系比重最大,而四川攀枝花龙洞的水质虽然含钴元素比另外两个更高,但由于溶解氧更多,NH3-N 的含量更小,水体不显富营养化。就整体而言,四川攀枝花龙洞得分高于重庆朱沱和湖北宜昌南津关。

将一个成对比较矩阵的 AHP 过程封装为函数,完整函数如下。

def AHP(A):
    m = len(A)  # 获取指标个数
    n = len(A[0])
    RI = [0,0, 0, 0.58, 0.90, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.51]
    R = np.linalg.matrix_rank(A)  # 求判断矩阵的秩
    V, D = np.linalg.eig(A)  # 求判断矩阵的特征值和特征向量,V特征值,D特征向量;
    list1 = list(V)
    B = np.max(list1)  # 最大特征值
    index = list1.index(B)
    C = D[:, index]  # 对应特征向量
    CI = (B - n) / (n - 1)  # 计算一致性检验指标CI
    CR = CI / RI[n]
    if CR < 0.10:
        print("CI=", CI.real)
        print("CR=", CR.real)
        print('对比矩阵A通过一致性检验,各向量权重向量Q为:')
        sum = np.sum(C)
        Q = C / sum  # 特征向量标准化
        print(Q.real)  # 输出权重向量
        return Q.real
    else:
        print("对比矩阵A未通过一致性检验,需对对比矩阵A重新构造")
        return 0

 7.1.3层次分析法代码

例7.1

import numpy as np

# 准则层和方案层的成对比较矩阵
criteria_matrix = np.array([
    [1, 1/5, 1/3, 1],
    [5, 1, 3, 5],
    [3, 1/3, 1, 3],
    [1, 1/5, 1/3, 1]
])

# 方案层的原始数据
data = np.array([
    [7.94, 9.47, 1.63, 0.077],  # 四川攀枝花龙洞
    [8.15, 9.00, 1.40, 0.417],  # 重庆朱沱
    [8.06, 8.45, 2.83, 0.203]   # 湖北宜昌南津关
])

# 计算权重的函数
def calculate_weights(matrix):
    eigenvalues, eigenvectors = np.linalg.eig(matrix)
    max_index = np.argmax(eigenvalues)
    eigenvector = eigenvectors[:, max_index] / np.sum(eigenvectors[:, max_index])
    return eigenvector

# 一致性检验的函数
def consistency_check(matrix):
    eigenvalues, _ = np.linalg.eig(matrix)
    max_eigenvalue = np.max(eigenvalues)
    CI = (max_eigenvalue - matrix.shape[0]) / (matrix.shape[0] - 1)
    RI_values = [0,0, 0, 0.58, 0.90, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.51]  # 根据矩阵阶数选择
    RI = RI_values[matrix.shape[0]]
    CR = CI / RI
    return CI, CR

# 标准化处理数据的函数
def normalize_data(data):
    max_values = np.max(data, axis=0)
    min_values = np.min(data, axis=0)
    normalized_data = (data - min_values) / (max_values - min_values)
    # 对CODMn和NH3-N进行逆极差标准化
    normalized_data[:, 2] = 1 - normalized_data[:, 2]
    normalized_data[:, 3] = 1 - normalized_data[:, 3]
    return normalized_data

# 计算方案得分的函数(修正后)
def calculate_scores(normalized_data, weights):
    return np.dot(normalized_data, weights)

# 主程序
def main():
    # 计算准则层权重
    criteria_weights = calculate_weights(criteria_matrix)
    print("准则层权重:", criteria_weights.real)

    # 进行一致性检验
    CI, CR = consistency_check(criteria_matrix)
    print("一致性指标CI:", CI.real)
    print("一致性比率CR:", CR.real)

    # 标准化处理数据
    normalized_data = normalize_data(data)

    # 计算方案的综合得分
    scores = calculate_scores(normalized_data, criteria_weights)
    print("各方案的综合得分:")
    for i, score in enumerate(scores):
        print(f"方案 {i+1}: {score.real}")  # Ensure to print real part of complex numbers

    # 根据得分对方案进行排序
    sorted_indices = scores.argsort()[::-1]
    print("方案排序(水质从好到差):", sorted_indices + 1)  # 将索引转换为实际方案编号

if __name__ == "__main__":
    main()

输出结果:

准则层权重: [0.09546368 0.55958606 0.24948658 0.09546368]
一致性指标CI: 0.014497820535966117
一致性比率CR: 0.0161086894844068
各方案的综合得分:
方案 1: 0.8644091087319299
方案 2: 0.6466878399762959
方案 3: 0.1146366370978105
方案排序(水质从好到差): [1 2 3]

  • 35
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值