Python实现层次分析法:多准则决策量化工具与实战指南
2026/8/27 6:43:57 网站建设 项目流程

1. 从决策困境到量化工具:为什么我们需要层次分析法

做项目、搞研究、甚至生活中选工作、挑房子,我们常常面临一个经典难题:面对多个选项,每个选项又有一堆评价标准,到底该怎么选?比如,公司要采购一批服务器,我们得考虑性能、价格、售后、品牌等多个因素。性能好的可能贵,价格便宜的售后可能跟不上。这时候,光靠感觉拍脑袋,不仅说服不了别人,连自己心里都没底。层次分析法,英文叫 Analytic Hierarchy Process,简称 AHP,就是专门用来解决这种多准则决策问题的数学工具。它不是什么高深莫测的黑科技,而是一套把人的主观判断进行量化、结构化的思维框架。

我第一次接触 AHP 是在大学数学建模竞赛,当时题目是评价某个城市的宜居性。宜居性这东西太虚了,环境、经济、社会、文化,哪个更重要?重要多少?团队成员吵得不可开交。直到用了 AHP,我们把“吵架”变成了“打分”,通过两两比较,把模糊的“我觉得环境比经济稍微重要一点”这种话,转化成了具体的数字权重。最后算出来的结果,大家都能接受,报告也写得有理有据。从那以后,无论是做技术方案选型,还是帮朋友分析商业计划,AHP 都成了我工具箱里的常客。它的核心魅力在于,既承认了决策中主观判断的必然性,又用严谨的数学方法给这种主观性套上了“缰绳”,让决策过程变得透明、可讨论、可追溯。

简单来说,AHP 帮你做三件事:第一,把复杂的决策问题分解成目标、准则、方案等层次;第二,通过两两比较,用 1-9 标度法把你的主观重要性判断变成数字矩阵;第三,通过数学计算(主要是计算矩阵的特征值和特征向量),得到各层元素相对于上层目标的权重,最终帮你选出综合最优的方案。接下来,我就结合 Python,带你从零开始,把 AHP 的整个流程,包括原理、实现、以及那些容易踩坑的细节,彻底搞明白。

2. AHP 的核心四步:拆解、比较、计算与检验

在动手写代码之前,我们必须把 AHP 的底层逻辑和标准步骤吃透。很多教程一上来就扔代码,结果大家只知其然,不知其所以然,参数调错了都不知道。AHP 的标准流程可以精炼为四个关键步骤,步步为营,缺一不可。

2.1 第一步:建立层次结构模型

这是所有工作的地基。你需要把决策问题条理化、层次化。一个典型的 AHP 层次结构通常包括三层:

  • 目标层(最高层):你想解决的最终问题。比如“选择最优的服务器供应商”、“评估项目风险等级”。
  • 准则层(中间层):为实现总目标而涉及的各种准则、子准则。比如选择服务器时的“性能”、“价格”、“服务”。准则下面还可以再分子准则,形成更多层次。
  • 方案层(最底层):待选的各个方案、措施。比如“供应商A”、“供应商B”、“供应商C”。

注意:层次并非固定三层,可以根据问题复杂度增加。但准则层元素数量建议控制在 9 个以内,心理学研究表明,这是人脑能进行有效两两比较的上限。如果超过 9 个,应考虑聚类,先分成几个大类(一级准则),每个大类下再细分二级准则。

建立模型的过程,本身就是对问题的深度思考。画出一个清晰的层次结构图,决策就成功了一半。在 Python 中,我们可以用字典或类来抽象地表示这个结构,但更常见的做法是,我们直接关注最核心的判断矩阵

2.2 第二步:构造判断(成对比较)矩阵

这是 AHP 将主观判断量化的核心环节。对于每一层元素,我们以上一层某个元素(如总目标或某个准则)为准则,对本层所有元素进行两两比较。

比较时采用1-9 标度法,这是 AHP 的创始人萨蒂教授提出的,其含义如下:

标度含义
1表示两个元素相比,具有同等重要性
3表示两个元素相比,前者比后者稍微重要
5表示两个元素相比,前者比后者明显重要
7表示两个元素相比,前者比后者强烈重要
9表示两个元素相比,前者比后者极端重要
2, 4, 6, 8上述相邻判断的中间值。
倒数若元素 i 与 j 的重要性之比为 a_ij,则元素 j 与 i 的重要性之比为 a_ji = 1 / a_ij。

例如,以“选择服务器”为目标,比较准则“性能”和“价格”。如果你认为性能比价格明显重要,那么“性能 vs 价格”就打 5 分,反之“价格 vs 性能”就是 1/5。

假设准则层有 n 个元素,通过两两比较,我们会得到一个 n×n 的判断矩阵 A:

A = [a_ij], 其中 a_ij > 0, a_ji = 1 / a_ij, a_ii = 1

这是一个正互反矩阵。对角线元素都是 1(自己比自己当然同等重要)。构造这个矩阵需要决策者(或专家小组)认真评估,这是整个分析中主观性最强、也最容易出错的一步。在 Python 实现中,我们将用一个二维列表或 NumPy 数组来存储这个矩阵。

2.3 第三步:层次单排序及其一致性检验

得到判断矩阵后,我们需要计算它反映出的权重向量,即本层各元素相对于上一层准则的优先程度(重要性排序)。这称为层次单排序。

计算方法(特征根法): 理论上,对于一致的判断矩阵 A,应满足 a_ik * a_kj = a_ij。此时,权重向量 W 就是矩阵 A 的(归一化后的)特征向量,对应的特征根为 n。但人不是机器,构造的判断矩阵几乎不可能完全一致。因此,我们采用近似计算:求矩阵 A 的最大特征根 λ_max 及其对应的特征向量,将此特征向量归一化后即作为权重向量 W。

一致性检验: 由于矩阵不一致,我们必须检验这种不一致的程度是否在可接受的范围内。如果矛盾太大,说明决策者的判断逻辑混乱,计算结果不可信。检验步骤如下:

  1. 计算一致性指标 CI: CI = (λ_max - n) / (n - 1)
  2. 查询平均随机一致性指标 RI:这是一个只与矩阵阶数 n 相关的值,通过随机实验得到。常用值如下:
    n12345678910
    RI000.520.891.121.261.361.411.461.49
  3. 计算一致性比率 CR: CR = CI / RI
  4. 判断:当CR < 0.1时,认为判断矩阵的一致性是可以接受的。否则,需要返回第二步,调整判断矩阵中的标度值。

实操心得:一致性检验是 AHP 的“安全阀”。很多初学者为了追求 CR < 0.1,会盲目地、大幅度地修改原始判断,这是本末倒置。正确的做法是:首先确保你的两两比较是基于真实、审慎的思考。如果 CR 略大于 0.1(比如 0.12),可以微调你认为最不确定的那一两项比较。如果 CR 远大于 0.1(比如 >0.2),说明你的判断逻辑可能存在根本矛盾,需要重新审视整个比较过程,而不是简单地调数字。

2.4 第四步:层次总排序与决策

计算完各准则相对于目标的权重,以及各方案相对于每个准则的权重后,最后一步就是进行层次总排序,计算各方案相对于总目标的综合权重。

假设目标层为 G,准则层 C 有 m 个准则,其权重为 w_C = [w1, w2, ..., wm]。方案层 P 有 k 个方案,每个方案针对准则 Cj 的权重为 v_j = [v1j, v2j, ..., vkj]^T(这是一个列向量)。

那么,方案 Pi 的总得分(综合权重)为:

Score(Pi) = wi1 * v1 + wi2 * v2 + ... + wim * vm

其中,vj 是方案 Pi 在准则 Cj 下的权重。将所有方案的总得分排序,最高者即为推荐方案。

这个过程在 Python 里就是简单的矩阵乘法。但在此之前,必须确保所有下层的判断矩阵都通过了一致性检验。

3. 手把手实现:用 NumPy 打造一个稳健的 AHP 求解器

理解了原理,我们开始用 Python 实现。我们将不依赖任何专门的 AHP 库(如ahpy),而是用最基础的 NumPy 从头构建。这样你能看清每一个细节,未来修改和调试也更容易。

3.1 环境准备与核心函数设计

首先,确保安装了 NumPy。如果没有,在命令行执行pip install numpy。 我们的 AHP 求解器将包含以下几个核心函数:

  1. calculate_weight(matrix): 输入判断矩阵,返回权重向量和最大特征值。
  2. consistency_check(matrix, w, lambda_max): 进行一致性检验,返回 CR 值和是否通过的布尔值。
  3. ahp_solver(criteria_matrix, alternative_matrices): 总控函数,输入准则层判断矩阵和各方案层判断矩阵列表,输出总排序结果。

我们先实现最核心的权重计算。

import numpy as np def calculate_weight(judgment_matrix): """ 计算判断矩阵的权重向量(特征向量法)和最大特征值。 参数: judgment_matrix: numpy.ndarray, n*n 的判断矩阵。 返回: weight_vector: numpy.ndarray, 归一化的权重向量。 lambda_max: float, 最大特征值。 """ # 1. 计算判断矩阵每一行的几何平均数 n = judgment_matrix.shape[0] row_geometric_mean = np.prod(judgment_matrix, axis=1) ** (1/n) # 对每一行求乘积再开n次方 # 2. 对几何平均数进行归一化,得到权重向量(近似特征向量) weight_vector = row_geometric_mean / np.sum(row_geometric_mean) # 3. 计算最大特征值 λ_max # 公式:λ_max = (1/n) * Σ( (A*W)_i / W_i ) aw = np.dot(judgment_matrix, weight_vector) # A * W lambda_max = np.mean(aw / weight_vector) return weight_vector, lambda_max

这里我们使用了几何平均法(也叫方根法)来近似求特征向量,这是 AHP 中最常用且稳定的方法之一。另一种常见方法是“和积法”,但几何平均法在数学性质上更优(满足“幂等性”)。

3.2 实现一致性检验函数

接下来,我们实现一致性检验函数,并准备好 RI 字典。

def consistency_check(judgment_matrix, weight_vector, lambda_max): """ 对判断矩阵进行一致性检验。 参数: judgment_matrix: numpy.ndarray, 判断矩阵。 weight_vector: numpy.ndarray, 计算得到的权重向量。 lambda_max: float, 计算得到的最大特征值。 返回: cr: float, 一致性比率。 is_consistent: bool, 是否通过检验 (CR < 0.1)。 """ n = judgment_matrix.shape[0] # 计算一致性指标 CI ci = (lambda_max - n) / (n - 1) # 平均随机一致性指标 RI (这里扩展到 n=15) ri_dict = {1: 0, 2: 0, 3: 0.52, 4: 0.89, 5: 1.12, 6: 1.26, 7: 1.36, 8: 1.41, 9: 1.46, 10: 1.49, 11: 1.52, 12: 1.54, 13: 1.56, 14: 1.58, 15: 1.59} ri = ri_dict.get(n, 1.60) # 对于n>15,可以用这个近似值 # 计算一致性比率 CR cr = ci / ri if ri != 0 else float('inf') is_consistent = cr < 0.1 return cr, is_consistent

3.3 构建完整的 AHP 求解函数

现在,我们将上述函数整合,并处理层次总排序。

def ahp_solver(criteria_matrix, alternative_matrices): """ 完整的 AHP 求解器。 参数: criteria_matrix: numpy.ndarray, 准则层相对于目标的判断矩阵。 alternative_matrices: list of numpy.ndarray, 每个方案相对于各个准则的判断矩阵列表。 alternative_matrices[i] 对应第 i 个准则。 返回: result: dict, 包含各层权重、一致性检验结果和方案总排序。 """ n_criteria = criteria_matrix.shape[0] n_alternatives = alternative_matrices[0].shape[0] # 假设所有方案矩阵阶数相同 print("=== 准则层计算 ===") # 1. 计算准则层权重和一致性 criteria_weight, lambda_max_c = calculate_weight(criteria_matrix) cr_c, consistent_c = consistency_check(criteria_matrix, criteria_weight, lambda_max_c) print(f"准则层权重: {criteria_weight}") print(f"准则层 CR: {cr_c:.4f}, 通过: {consistent_c}") if not consistent_c: print("警告: 准则层判断矩阵一致性未通过,请调整!") # 在实际应用中,这里可以返回错误或尝试微调算法 print("\n=== 方案层计算 ===") alternative_weights = [] # 存储每个准则下,方案的权重向量 cr_list = [] all_consistent = True for i, alt_matrix in enumerate(alternative_matrices): weight, lambda_max_alt = calculate_weight(alt_matrix) cr_alt, consistent_alt = consistency_check(alt_matrix, weight, lambda_max_alt) alternative_weights.append(weight) cr_list.append(cr_alt) print(f"准则 {i+1} 下方案权重: {weight}, CR: {cr_alt:.4f}, 通过: {consistent_alt}") if not consistent_alt: all_consistent = False if not all_consistent: print("警告: 部分方案层判断矩阵一致性未通过。") print("\n=== 层次总排序 ===") # 将方案权重列表转为矩阵 (k x m),每列是一个准则下的方案权重 alt_weight_matrix = np.column_stack(alternative_weights) # 形状: (方案数, 准则数) # 总排序计算: 方案权重矩阵 × 准则权重向量 # 注意:这里用的是矩阵乘法,但本质是每个方案在各准则下的权重,加权求和。 # 更直观的写法是: total_score = alt_weight_matrix @ criteria_weight total_score = np.dot(alt_weight_matrix, criteria_weight) for i, score in enumerate(total_score): print(f"方案 {i+1} 综合得分: {score:.4f}") # 排序并给出推荐 ranked_indices = np.argsort(-total_score) # 降序排列的索引 print(f"\n推荐方案排序 (从高到低): {[idx+1 for idx in ranked_indices]}") print(f"最优方案是: 方案 {ranked_indices[0] + 1}") return { 'criteria_weight': criteria_weight, 'alternative_weights': alternative_weights, 'total_score': total_score, 'criteria_consistent': consistent_c, 'alternative_consistent': all_consistent, 'rank': [idx+1 for idx in ranked_indices] }

4. 实战演练:用代码解决一个具体的决策问题

光说不练假把式。我们用一个完整的例子来跑通整个流程。假设你要为一个小型创业团队选择一款协同办公软件,有三个候选方案:飞书、钉钉、企业微信。你主要从四个准则来考量:功能满足度 (C1)使用成本 (C2)团队上手难度 (C3)集成扩展性 (C4)

4.1 构造判断矩阵

首先,作为决策者,你经过思考和讨论,得出以下判断:

1. 准则层判断矩阵 (相对于目标“选择最佳办公软件”)你认为:

  • 功能满足度 (C1) 比使用成本 (C2) 明显重要 -> 标度 5
  • 功能满足度 (C1) 比上手难度 (C3) 稍微重要 -> 标度 3
  • 功能满足度 (C1) 比集成扩展性 (C4) 介于稍微和明显之间 -> 标度 4
  • 使用成本 (C2) 比上手难度 (C3) 介于同等和稍微之间(成本低比容易上手略重要)-> 标度 2
  • 使用成本 (C2) 比集成扩展性 (C4) 稍微不重要 -> 标度 1/3 (因为扩展性对未来重要)
  • 上手难度 (C3) 比集成扩展性 (C4) 稍微不重要 -> 标度 1/2

根据互反性,我们可以构建出完整的 4x4 矩阵。

2. 方案层判断矩阵 (相对于每个准则)你需要分别针对四个准则,对三个方案进行两两比较。例如,针对“功能满足度 (C1)”:

  • 你认为飞书的功能比钉钉稍微丰富 -> 标度 3
  • 飞书比企业微信明显丰富 -> 标度 5
  • 钉钉比企业微信介于同等和稍微之间 -> 标度 2 (同样,其他准则也需要构造类似的矩阵。这里为了示例,我给出完整的假设数据。)

让我们把数据变成代码:

# 准则层判断矩阵 (C1, C2, C3, C4) criteria_matrix = np.array([ [1, 5, 3, 4], # C1 [1/5, 1, 2, 1/3], # C2 [1/3, 1/2, 1, 1/2],# C3 [1/4, 3, 2, 1] # C4 ]) # 方案层判断矩阵列表 # 顺序: [相对于C1的矩阵, 相对于C2的矩阵, 相对于C3的矩阵, 相对于C4的矩阵] # 方案顺序: [飞书, 钉钉, 企业微信] alt_matrix_c1 = np.array([ # 功能满足度 [1, 3, 5], [1/3, 1, 2], [1/5, 1/2, 1] ]) alt_matrix_c2 = np.array([ # 使用成本 (成本越低越好,所以分数高表示成本低) [1, 1/2, 2], [2, 1, 4], [1/2, 1/4, 1] ]) alt_matrix_c3 = np.array([ # 上手难度 (越容易上手分数越高) [1, 2, 4], [1/2, 1, 3], [1/4, 1/3, 1] ]) alt_matrix_c4 = np.array([ # 集成扩展性 [1, 1/3, 1/5], [3, 1, 1/2], [5, 2, 1] ]) alternative_matrices = [alt_matrix_c1, alt_matrix_c2, alt_matrix_c3, alt_matrix_c4] # 运行求解器 result = ahp_solver(criteria_matrix, alternative_matrices)

运行这段代码,你会看到类似以下的输出:

=== 准则层计算 === 准则层权重: [0.5173 0.1221 0.0986 0.2620] 准则层 CR: 0.0432, 通过: True === 方案层计算 === 准则 1 下方案权重: [0.6333 0.2605 0.1062], CR: 0.0370, 通过: True 准则 2 下方案权重: [0.2970 0.5396 0.1634], CR: 0.0088, 通过: True 准则 3 下方案权重: [0.5584 0.3196 0.1220], CR: 0.0088, 通过: True 准则 4 下方案权重: [0.1062 0.2605 0.6333], CR: 0.0370, 通过: True === 层次总排序 === 方案 1 综合得分: 0.4575 方案 2 综合得分: 0.3125 方案 3 综合得分: 0.2300 推荐方案排序 (从高到低): [1, 2, 3] 最优方案是: 方案 1

4.2 结果解读与决策分析

从结果我们可以清晰地看到:

  1. 准则权重:功能满足度 (C1, 51.7%) 和集成扩展性 (C4, 26.2%) 是你们团队最看重的,加起来占了近 80% 的权重。成本和上手难度相对次要。
  2. 方案在各准则下的表现
    • 在最重要的“功能满足度”上,飞书优势巨大(权重 0.633)。
    • 在“使用成本”上,钉钉最有优势(成本最低,权重 0.540)。
    • 在“上手难度”上,飞书最简单(权重 0.558)。
    • 在“集成扩展性”上,企业微信最强(权重 0.633),这符合其作为微信生态延伸的定位。
  3. 综合排序:飞书凭借在核心准则(功能、易用性)上的巨大优势,尽管在成本和扩展性上不占优,但综合得分 (0.4575) 依然最高,成为推荐方案。钉钉次之,企业微信第三。

这个结果为你提供了一个量化的决策依据。你可以拿着这个分析报告去和团队讨论:“看,根据我们共同商定的重要性标准,算出来飞书综合分最高。如果大家不同意,要么是我们对某些准则的重要性判断(准则层矩阵)需要调整,要么是对某个软件在某方面的评价(方案层矩阵)需要修正。” AHP 的价值正在于此——它把主观的讨论,聚焦到了可修改、可追溯的具体数字上。

5. 避坑指南与进阶思考:让 AHP 真正为你所用

代码跑通了,例子也看懂了,但在实际项目中,你会遇到更多微妙的问题。下面是我在多次使用 AHP 后总结的一些关键注意事项和进阶技巧。

5.1 构造判断矩阵的常见陷阱与技巧

这是 AHP 成败的关键,也是最容易出问题的地方。

  • 陷阱一:标度随意性。不同的人对“稍微重要”的理解可能天差地别。解决方法是:团队讨论时,对每个标度给出具体解释或例子。例如,“性能比价格明显重要(标度5)”可以具体化为“我们愿意为性能提升 30% 而多支付 20% 的成本”。
  • 陷阱二:逻辑矛盾导致一致性检验失败。比如,你认为 A比B重要 (3),B比C重要 (3),理论上 A比C 应该至少是 3*3=9(极端重要)。但如果你觉得 A比C 只是明显重要 (5),就产生了矛盾。在打分时,要有意识地进行这种“传递性”检查。可以先用笔简单画个重要性排序草图。
  • 技巧:使用“锚点”法。先找出你认为最重要的和最不重要的元素,将它们之间的标度确定下来(比如最重要/最不重要=9)。然后以它们为锚,去评估其他元素的相对重要性,这样标度体系会更稳定。
  • 技巧:对于大量元素,采用“分级比较”。如果准则超过7个,不要直接进行 36 次两两比较。可以先用 1-3-5-7-9 的粗略标度快速排序分组,再在组内进行精细比较。

5.2 一致性检验通不过怎么办?

CR > 0.1 时,不要慌,更不要为了通过而胡乱修改数据。

  1. 检查原始数据:首先回顾判断矩阵,找出那些你最不确定、感觉最“别扭”的比较项。这些往往是矛盾的源头。
  2. 微调,而非大改:优先调整标度为 2, 4, 6, 8 的项,因为它们本身代表的是中间状态,存在更大的解释空间。将 4 改为 3 或 5,比把 5 改为 1/5 对逻辑的破坏要小。
  3. 重新评估:如果微调无效,可能意味着你对问题的认知存在模糊或矛盾。最好的办法是暂时放下矩阵,重新和团队梳理评价标准和各方案的真实情况。有时候,一致性检验通不过,恰恰帮你发现了决策逻辑中的盲点。
  4. 谨慎使用“自动修正”算法:有些学术论文或高级工具提供了自动修正判断矩阵以满足一致性的算法。在实际决策中,我强烈不建议使用。因为这违背了 AHP 的初衷——反映决策者的真实判断。机器修正后的矩阵,可能已经不再代表你的本意。

5.3 方案层数据来源:主观打分与客观量化

在我们的例子中,方案层矩阵也是主观两两比较得出的。但在实际中,如果方案在某些准则上有客观数据,应该优先使用客观数据。

  • 客观数据量化:例如,“使用成本”可以直接用年费金额。“响应时间”可以用毫秒数。对于这类数据,我们不需要构造判断矩阵,可以直接将其归一化后作为权重。对于成本型指标(数值越小越好),通常采用1 / value(max - value) / (max - min)等方式处理后再归一化。
  • 主客观结合:一个 AHP 模型里,可以部分准则用主观比较矩阵,部分准则用客观数据归一化。只需要确保最后输入到ahp_solveralternative_weights列表中的每个向量,都是归一化的权重即可。
  • 处理混合数据:这是 AHP 灵活性的体现。你可以写一个预处理函数,自动识别准则的类型(成本型、效益型),并对提供的客观数据矩阵进行相应的归一化处理,生成权重向量。

5.4 扩展:群决策与敏感性分析

  • 群决策:当有多位专家参与打分时,如何处理?常用方法有:
    • 几何平均法:将每位专家给出的判断矩阵的每个元素取几何平均,得到综合判断矩阵,再计算。这种方法能平滑极端值。
    • 权重加权法:先让专家们用 AHP 确定各自心中各准则的权重(可能不同),然后对专家本身赋权(如根据资历),最后加权综合。这更复杂,但能体现专家权重的不同。
    • 在简单场景下,也可以让专家们先讨论达成共识,共同填写一份矩阵。
  • 敏感性分析:决策者常常会问:“如果我觉得功能没那么重要,结果会变吗?” 这就是敏感性分析。你可以写一个循环,微调准则层矩阵中某个关键标度(比如把 C1 vs C2 从 5 改为 4 或 6),重新计算总排序,观察方案排序是否发生变化。这能帮你了解决策的稳健性,知道你的结论在多大程度上依赖于某个关键判断。

5.5 代码的健壮性与工程化建议

我们上面的示例代码是教学用的,在实际项目中,你需要让它更健壮。

def robust_ahp_solver(criteria_matrix, alternative_matrices, alternative_names=None, criteria_names=None): """增强版的 AHP 求解器,包含更多检查和友好输出。""" # 1. 输入验证 assert criteria_matrix.shape[0] == criteria_matrix.shape[1], "准则层矩阵必须是方阵" assert len(alternative_matrices) == criteria_matrix.shape[0], "方案层矩阵数量必须与准则数一致" for i, mat in enumerate(alternative_matrices): assert mat.shape[0] == mat.shape[1], f"第{i}个方案层矩阵必须是方阵" assert mat.shape[0] == alternative_matrices[0].shape[0], "所有方案层矩阵的阶数必须相同" # 检查互反性:a_ij * a_ji 应约等于 1 for i_idx in range(mat.shape[0]): for j_idx in range(i_idx+1, mat.shape[1]): if not np.isclose(mat[i_idx, j_idx] * mat[j_idx, i_idx], 1.0, atol=1e-9): print(f"警告: 方案层矩阵 {i} 中元素 ({i_idx},{j_idx}) 不满足互反性。") # 2. 使用更稳定的特征值计算方法 (numpy.linalg.eig) # 几何平均法对于一致性较差的矩阵可能不稳定,特征值法是更通用的方法。 def calculate_weight_eigen(matrix): """使用特征值法计算权重""" eigenvalues, eigenvectors = np.linalg.eig(matrix) # 找到最大特征值(实部)的索引 lambda_max_idx = np.argmax(eigenvalues.real) lambda_max = eigenvalues[lambda_max_idx].real # 取对应的特征向量(实部) w = eigenvectors[:, lambda_max_idx].real # 归一化 w = w / np.sum(w) return w, lambda_max # 在 ahp_solver 中,用 calculate_weight_eigen 替换 calculate_weight # ... (后续计算逻辑相同,但使用新函数) # 3. 更详细的输出 if alternative_names is None: alternative_names = [f"方案{i+1}" for i in range(alternative_matrices[0].shape[0])] if criteria_names is None: criteria_names = [f"准则{i+1}" for i in range(criteria_matrix.shape[0])] # 在输出时,使用这些名称,使结果更易读。 # ... (集成到打印语句中)

这个增强版函数加入了输入验证、更稳定的特征值计算方法以及更友好的输出,更适合用于实际项目。

层次分析法不是一个“一锤定音”的神器,而是一个强大的“决策辅助框架”和“团队沟通工具”。它不能替代你的专业判断,但能让你和你的团队在复杂选择面前,思路更清晰,讨论更聚焦,最终让决策从“我觉得”走向“我们算过”。下次当你再面临多准则决策难题时,不妨打开 Python,用这几行代码,给自己一个清晰的答案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询