学习笔记
数学建模算法:层次分析法
文章目录
模型定位
层次分析法「The analytic hierarchy process」是在对复杂的决策问题的本质、影响因素及其内在关系等进行深入分析的基础上,利用较少的定量信息使决策的思维过程数学化,从而为多目标、多准则或无结构特性的复杂决策问题提供简便的决策方法。
模型共分为三个层级:
- 目标层:结果输出层,确定目标是什么?
- 准则层:影响因素集,决定这一结果的因素有什么?
- 方案层:备选集,从哪些样本中选择?
模型适用于评价类、排名类、决策类问题
模型流程
数据预处理
在计算中,需要将不同准则的数量级统一,这个过程称为归一化,将一组统一标准的数据视为列向量,把数据化为在总数中的占比即可,范围为(0,1): $$ x_i = \frac{x_i}{\sum_{k=1}^nx_k}\ ,\ i\in{1,2,\dots,n} $$
生成判断矩阵
两两比较每个准则(指标)的重要性,记为$a_{ij}$, 来表示相对于指标j,指标i的重要性,且满足: $$ a_{ij} = \frac{1}{a_{ji}} $$
| $a_{ij}$ | 含义 |
|---|---|
| 1 | 指标$i$与指标$j$相同重要 |
| 3 | 指标$i$比指标$j$稍微重要 |
| 5 | 指标$i$比指标$j$明显重要 |
| 7 | 指标$i$比指标$j$强烈重要 |
| 9 | 指标$i$比指标$j$极端重要 |
注:2,4,6,8表示在两者之间
一致性检验
由于重要性的比较是单看两者的主观评价,结果不可避免会产生矛盾,我们虽然不能追求完美一致,但是这一判断矩阵必须通过一致性检验,确保重要性差异较为一致: $$ CR = \frac{CI}{RI} , CI = \frac{\lambda_{max}-n}{n-1} $$ 其中$\lambda_{max}$为判断矩阵的最大特征值,$RI$为常数,在不同因素数下有不同取值:
| n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| RI | 0 | 0 | 0.52 | 0.89 | 1.12 | 1.26 | 1.36 | 1.41 | 1.46 | 1.49 |
- 若$CR \leq 0.1 $ : 通过一致性检验
- 若$CR > 0.1 $ : 重新生成判断矩阵
权重矩阵
- 矩阵按列归一化:即每个数值除以所在列的和
- 每行求平均降维即可
代码实现
Python Version
import numpy as np
# 准则重要性矩阵
A = np.array([[1, 2, 3, 5],
[1 / 2, 1, 1 / 2, 2],
[1 / 3, 2, 1, 2],
[1 / 5, 1 / 2, 1 / 2, 1]])
[n, m] = A.shape
# 一致性检验
V, D = np.linalg.eig(A)
maxlam = np.max(V)
CI = (maxlam - 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]
if CR >= 0.1:
print('没有通过一致性检验\n')
else:
print('通过一致性检验\n')
# 计算权重
Asum = np.sum(A, axis=0)
Aprogress = A/(np.ones((n, 1), dtype=np.int64) * Asum)
W = np.average(Aprogress, axis=1)
Matlab Version
%输入判断矩阵
A = [1 2 3 5
1/2 1 1/2 2
1/3 2 1 2
1/5 1/2 1/2 1];
%一致性检验
maxlam = max(eig(A));
[~, n] = size(A);
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];
CI = (maxlam - n) / (n-1);
CR = CI / RI(n);
if CR < 0.10
disp('通过一致性检验')
else
disp('不通过一致性检验')
return % 终止运行
end
%计算权重向量
[n,~] = size(A);
Asum = sum(A,1); % 按列求和
Aprogress = A./(ones(n,1)*Asum);
W = sum(Aprogress, 2)./n;