层次分析法(AHP)和模糊层次分析法(FAHP)实现

 基础理论介绍:层次分析法(AHP)和模糊层次分析法(FAHP)-CSDN博客

本篇博客用来记录层次分析法(AHP)和模糊层次分析法(FAHP)实现过程,进一步学习两种方法的求解过程,体会两种算法的不同之处。

一、层次分析法(AHP)

这篇博文中所提出的案例作为待决策事件。

大体步骤主要包括四个:层次结构模型的构建;构造判断矩阵;层次单排序及其一致性检验;层次总排序及其一致性检验(没有决策层的话可以省略此步骤)。

推荐工具SPSSPRO

1.层次结构模型的构建

将此待决策事件分解为:

  • 目标层:选择旅行地
  • 准则层:选择旅行目的地考虑的因素(景色、费用、居住、饮食、旅途)
  • 方案层:旅游目的地(苏杭、北戴河、桂林)
2.构造判断矩阵 
景色费用居住饮食旅途
景色1551/38
费用1/511/41/62
居住1/5411/53
饮食36516
旅途1/81/21/31/61

对角线上是各个指标对自己的判断,自身对标自身均是1:1,其他相对重要性的判断依据下表进行判别。

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

层次单排序是指针对上一层某元素将本层中所有元素两两评比,并开展层次排序, 进行重要顺序的排列。计算方法在基础理论介绍中有详细解释,这里就不再赘述。

4.层次总排序及其一致性检验 

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

专业性解释:

设B层对A层中因素的层次排序一致性指标为CIi,随机性一致性指标为RIi,则层次总排序的一致性比率为:

同样也是通过看CR是否小于0.1判断是否满足一致性检验 。

通俗来说,就是将准则层的步骤再重复一遍,即:

景色苏杭北戴河桂林
苏杭125
北戴河1/212
桂林1/51/21
费用苏杭北戴河桂林
苏杭11/31/8
北戴河311/3
桂林831
居住苏杭北戴河桂林
苏杭113
北戴河113
桂林1/31/31
饮食苏杭北戴河桂林
苏杭134
北戴河1/311
桂林1/411
旅途苏杭北戴河桂林
苏杭111/4
北戴河111/4
桂林441

计算出的权重向量分别为:

苏杭北戴河桂林
景色0.59540.27640.1283
苏杭北戴河桂林
费用0.08190.23630.6817
苏杭北戴河桂林
居住0.42860.42860.1429
苏杭北戴河桂林
饮食0.63370.19190.1744
苏杭北戴河桂林
旅途0.16670.16670.6667

因此,对于苏杭这个旅行地方案来说,总得分为:

苏杭在景色上的得分*景色的权重+苏杭在费用上的得分*费用的权重+苏杭在居住上的得分*居住的权重+苏杭在饮食上的得分*饮食的权重+苏杭在旅途上的得分*旅途的权重=0.5954*0.3104+0.819*0.0591+0.4286*0.1157+0.6337*0.4716+0.1667*0.0432=0.5889

同理算出,北戴河和桂林方案的得分为0.2471和0.2077

(这里就必须推荐SPSSPRO-免费专业的在线数据分析平台,真的非常好用,不用自己去计算,而且在代码里面引用比较方便)

代码部分
import numpy as np
from functools import reduce

def ahp_method(dataset, wd = 'm'):
    # 随机一致性指标R.I.(inc_rat)
    inc_rat  = np.array([0, 0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.51, 1.48, 1.56, 1.57, 1.59])
    # 数据深复制
    X        = np.copy(dataset)
    # 生成权重向量
    weights  = np.zeros(X.shape[1])
    # 根据权重计算方法来确定各个权重
    if (wd == 'm' or wd == 'mean'):  #均值
        weights  = np.mean(X/np.sum(X, axis = 0), axis = 1)
    elif (wd == 'g' or wd == 'geometric'):  #几何
        for i in range (0, X.shape[1]):
            weights[i] = reduce( (lambda x, y: x * y), X[i,:])**(1/X.shape[1])
        weights = weights/np.sum(weights)
    # 计算特征根向量
    vector   = np.sum(X*weights, axis = 1)/weights
    # 获得平均特征根
    lamb_max = np.mean(vector)
    # 计算一致性指标
    cons_ind = (lamb_max - X.shape[1])/(X.shape[1] - 1)
    # 一致性判断
    rc       = cons_ind/inc_rat[X.shape[1]]
    return weights, rc

##判断矩阵和打分矩阵
A = np.array([
    [1, 5, 5, 1 / 3, 8],
    [1 / 5, 1, 1 / 4, 1 / 6, 2],
    [1 / 5, 4, 1, 1 / 5, 3],
    [3, 6, 5, 1, 6],
    [1 / 8, 1 / 2, 1 / 3, 1 / 6, 1],
])
A_1 = np.array([
    [1, 2, 5],
    [1 / 2, 1, 2],
    [1 / 5, 1 / 2, 1],
])
A_2 = np.array([
    [1, 1 / 3, 1 / 8],
    [3, 1, 1 / 3],
    [8, 3, 1],
])
A_3 = np.array([
    [1, 1, 3],
    [1, 1, 3],
    [1 / 3, 1 / 3, 1],
])
A_4 = np.array([
    [1, 1 / 3, 4],
    [1 / 3, 1, 1],
    [1 / 4, 1, 1],
])
A_5 = np.array([
    [1, 1, 1 / 4],
    [1, 1, 1 / 4],
    [4, 4, 1],
])

# 计算权重和RI
weight_A, RC_A = ahp_method(A)
print('A的权重为:', weight_A)
print('A的RC为:', RC_A)
print()

weight_A1, RC_A1 = ahp_method(A_1)
weight_A2, RC_A2 = ahp_method(A_2)
weight_A3, RC_A3 = ahp_method(A_3)
weight_A4, RC_A4 = ahp_method(A_4)
weight_A5, RC_A5 = ahp_method(A_5)
print('A1的权重为:', weight_A1)
print('A1的RC为:', RC_A1)
print('A2的权重为:', weight_A2)
print('A2的RC为:', RC_A2)
print('A3的权重为:', weight_A3)
print('A3的RC为:', RC_A3)
print('A4的权重为:', weight_A4)
print('A4的RC为:', RC_A4)
print('A5的权重为:', weight_A5)
print('A5的RC为:', RC_A5)

## 构建V矩阵
V = np.vstack((weight_A1, weight_A2, weight_A3, weight_A4, weight_A5))
print(V)

scores = np.matmul(weight_A, V)
print('综合评分为:', scores)

二、模糊层次分析法(FAHP)

背景:三角模糊数概念

三角模糊数 ,分别为下界、中值和上界,其隶属函数表示为:

假设有 和,则有:

标题语言术语及其对应的三角模糊数
1.建立三角模糊判断矩阵

已知第K个专家评价结果:

2.计算专家判断平均数,更新判断矩阵

 当存在K个专家时,计算专家判断的平均数,表达式如下:

 则更新后的判断矩阵为:

 3.计算几何平均值

 计算每个标准的模糊判断值的几何平均值,如下:

 4.计算模糊权重

求解每个的矢量和,求矢量和向量的逆向量,计算与矢量和向量的逆向量,如下:

 5.反模糊化计算

  6.归一化处理

代码部分

 

import numpy as np

def fuzzy_ahp_method(dataset):
    '''
    dataset: 专家判断矩阵,n*n*3,n表示指标数
    '''
    row_sum = []
    s_row = []
    f_w = []  # 模糊权重
    d_w = []  # 去模糊权重
    # 一致性检测指标
    inc_rat = np.array([0, 0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49, 1.51, 1.48, 1.56, 1.57, 1.59])
    # 模糊判断矩阵转为清晰判断矩阵
    X = [(item[0] + 4 * item[1] + item[2]) / 6 for i in range(0, len(dataset)) for item in dataset[i]]  # 三角数转为模糊数
    X = np.asarray(X)  # 列表转数组
    X = np.reshape(X, (len(dataset), len(dataset)))  # 转为n*n矩阵

    # S4. 计算每个准则的模糊比较值的几何平均值r_i(公式4)
    for i in range(0, len(dataset)):
        a, b, c = 1, 1, 1
        for j in range(0, len(dataset[i])):
            d, e, f = dataset[i][j]
            # 计算公式(4)的括号内部分: r_s = \prod_{j=1}^n d_ij
            a, b, c = a * d, b * e, c * f
        row_sum.append((a, b, c))
    L, M, U = 0, 0, 0
    for i in range(0, len(row_sum)):
        a, b, c = row_sum[i]
        # 计算公式(4)的括号外部分: s_r = (r_s)^(1/n)
        a, b, c = a ** (1 / len(dataset)), b ** (1 / len(dataset)), c ** (1 / len(dataset))
        s_row.append((a, b, c))
        # 计算公式(5)中⨁运算部分:R5 = r1⨁r2⨁...⨁rn
        L = L + a
        M = M + b
        U = U + c

    for i in range(0, len(s_row)):
        a, b, c = s_row[i]
        # 计算公式公式(5)中⨂运算部分:wi = ri⨂R5
        a, b, c = a * (U ** -1), b * (M ** -1), c * (L ** -1)
        # 模糊权重
        f_w.append((a, b, c))
        # 计算公式(6):去模糊权重
        d_w.append((a + b + c) / 3)
    # 计算公式(7): 归一化权重
    n_w = [item / sum(d_w) for item in d_w]
    # 计算特征根向量
    vector = np.sum(X * n_w, axis=1) / n_w
    # 获得平均特征根
    lamb_max = np.mean(vector)
    # 计算一致性指标
    cons_ind = (lamb_max - X.shape[1]) / (X.shape[1] - 1)
    # 一致性判断
    rc = cons_ind / inc_rat[X.shape[1]]
    return f_w, d_w, n_w, rc


dataset = list([
    [(1, 1, 1), (4, 5, 6), (3, 4, 5), (6, 7, 8)],  # g1
    [(1 / 6, 1 / 5, 1 / 4), (1, 1, 1), (1 / 3, 1 / 2, 1 / 1), (2, 3, 4)],  # g2
    [(1 / 5, 1 / 4, 1 / 3), (1, 2, 3), (1, 1, 1), (2, 3, 4)],  # g3
    [(1 / 8, 1 / 7, 1 / 6), (1 / 4, 1 / 3, 1 / 2), (1 / 4, 1 / 3, 1 / 2), (1, 1, 1)]  # g4
])
fuzzy_weights, defuzzified_weights, normalized_weights, rc = fuzzy_ahp_method(dataset)
print('模糊权重')
for i in range(0, len(fuzzy_weights)):
    print('g' + str(i + 1) + ': ', np.around(fuzzy_weights[i], 3))
print('清晰权重')
for i in range(0, len(defuzzified_weights)):
    print('g' + str(i + 1) + ': ', round(defuzzified_weights[i], 3))
print('归一化权重')
for i in range(0, len(normalized_weights)):
    print('g' + str(i + 1) + ': ', round(normalized_weights[i], 3))

print('一致性判断')
print('RC: ' + str(round(rc, 2)))
if (rc > 0.10):
    print('The solution is inconsistent, the pairwise comparisons must be reviewed')
else:
    print('The solution is consistent')

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AHP层次分析法)是一种多层次决策方法,用于在多个选项之间进行决策。以下是使用Java实现AHP算法的一些步骤: 1. 定义标准矩阵,即将不同的决策因素分为等级,并确定它们之间的相对权重。 例如,我们可以使用二维数组来表示标准矩阵。假设我们有3个因素A、B、C,其中A对于B、C的相对重要性为2:1,而B对于C的相对重要性为3:1,则标准矩阵可以表示为: double[][] matrix = { {1.0, 2.0, 1.0/3.0}, {0.5, 1.0, 1.0/3.0}, {3.0, 3.0, 1.0} }; 2. 计算矩阵的一致性指标和随机一致性指标。AHP要求矩阵必须满足一致性,否则无法得到可靠的结果。计算矩阵一致性的方法是计算一致性指标CI,以及与随机一致性指标CR进行比较。 例如,我们可以使用下面的代码来计算矩阵的一致性指标: double[] weights = AHP.calculateWeights(matrix); double ci = AHP.calculateCI(matrix, weights); double cr = AHP.calculateCR(matrix); 3. 根据计算出来的权重,进行决策。 例如,我们可以使用下面的代码来获取权重,然后使用它们来进行决策: double[] weights = AHP.calculateWeights(matrix); int bestOptionIndex = AHP.getBestOptionIndex(weights); 其中,getBestOptionIndex方法返回具有最高权重的选项的索引。 下面是完整的AHP实现示例代码: ```java import java.util.Arrays; public class AHP { public static void main(String[] args) { double[][] matrix = { {1.0, 2.0, 1.0/3.0}, {0.5, 1.0, 1.0/3.0}, {3.0, 3.0, 1.0} }; double[] weights = calculateWeights(matrix); System.out.println("Weights: " + Arrays.toString(weights)); int bestOptionIndex = getBestOptionIndex(weights); System.out.println("Best option index: " + bestOptionIndex); } public static double[] calculateWeights(double[][] matrix) { int n = matrix.length; double[] weights = new double[n]; for (int j = 0; j < n; j++) { double sum = 0.0; for (int i = 0; i < n; i++) { sum += matrix[i][j]; } double columnSum = 0.0; for (int i = 0; i < n; i++) { matrix[i][j] /= sum; columnSum += matrix[i][j];
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值