正在加载中...

展开本页目录
算法教程PROMETHEE-偏好排序法

PROMETHEE-偏好排序法

No.093 · 在线教程

PROMETHEE(Preference Ranking Organization METHod for Enrichment Evaluation,偏好排序法)是一类基于成对比较偏好关系的多指标评价方法。与直接构造单一综合得分不同,PROMETHEE 的核心思想是:先比较任意…

PROMETHEE-偏好排序法

1. 方法概述

PROMETHEE(Preference Ranking Organization METHod for Enrichment Evaluation,偏好排序法)是一类基于成对比较偏好关系的多指标评价方法。与直接构造单一综合得分不同,PROMETHEE 的核心思想是:先比较任意两个方案在各指标上的优劣差异,再通过偏好函数把这种差异映射为偏好强度,最后用正流、负流与净流完成排序。

就本项目当前实现而言,core/promethee_calculator.py 实际执行的是 PROMETHEE II 路径,也就是以净流值 \(\phi\) 作为最终排序依据。整体计算链为:

  • 读取“方案列 + 指标列”的原始数据;
  • 支持正向指标、负向指标与适度指标;
  • 对原始矩阵做标准化;
  • 用熵权法或自定义权重得到指标权重;
  • 基于所选偏好函数构造全局偏好矩阵;
  • 计算正流、负流和净流;
  • 按净流值降序得到最终排名。

需要特别说明的是:虽然核心公开接口名称仍保留为 calculate_topsis(),但其真实计算内容已经是 PROMETHEE II,而不是 TOPSIS。

设共有 \(m\) 个方案、\(n\) 个指标,原始决策矩阵记为

$$ X=(x_{ij})_{m\times n}, \quad i=1,2,\ldots,m, \quad j=1,2,\ldots,n \tag{1} $$

设权重向量为

$$ w=\big(w_1,w_2,\ldots,w_n\big)^\top, \quad w_j\ge 0, \quad \sum_{j=1}^{n}w_j=1 \tag{2} $$

项目最终结果表中的核心列为:

  • phi_plus
  • phi_minus
  • phi
  • rank

其中 净流值 \(\phi\) 越大,方案越优

2. 输入结构与项目流程

2.1 输入数据结构

上传页 ui/upload_widget.py 支持 .xlsx.xls.csv 文件;结合 utils/data_validator.py,当前项目对输入数据要求:

  • 第 1 列为方案或对象名称;
  • 第 2 列及以后为指标列;
  • 指标列必须全部可转为数值;
  • 不允许空值;
  • 方案名称不允许重复;
  • 不允许常数列。

因此,进入核心类 PROMETHEECalculator 的标准输入形式为

$$ \mathcal{D}=\{A_i,\ x_{i1},x_{i2},\ldots,x_{in}\}_{i=1}^{m} \tag{3} $$

2.2 界面参数流程

主窗口 ui/main_window.py 的标准流程为:

  1. 上传数据;
  2. 选择参与计算的指标;
  3. 为每个指标设定类型;
  4. 在方法页选择标准化方式、权重方式和偏好函数;
  5. 结果页调用 calculate_topsis() 完成 PROMETHEE II 计算并导出结果。

当前方法页 ui/methods_widget.py 提供的参数包括:

  • normalizationmin-maxz-score
  • weight_methodentropycustom
  • pref_functionusualu-shapev-shapelevellineargaussian
  • pref_qpref_ppref_s:偏好函数参数。

需要特别说明的是:当前实现中的 \(q\)、\(p\)、\(s\) 参数是 对所有指标统一生效 的,而不是逐指标单独配置。

3. 指标类型与标准化口径

3.1 指标类型

当前模块支持三类指标:

  • 正向指标:值越大越优;
  • 负向指标:值越小越优;
  • 适度指标:值越接近目标值越优。

3.2 适度指标处理

_normalize() 中,若第 \(j\) 个指标被设为适度指标,程序先按如下方式转换:

$$ z_{ij}=1-\left|x_{ij}-t_j\right| \tag{4} $$

其中 \(t_j\) 表示该指标的目标值。若用户没有显式提供 moderate_values,核心会自动回退为该列中位数:

$$ t_j= \begin{cases} \text{用户设定值}, & \text{若已提供}\\ \operatorname{median}(x_{\cdot j}), & \text{否则} \end{cases} \tag{5} $$

这意味着:

  • 正常 UI 流程下,适度指标通常会要求用户输入标准值;
  • 直接调用核心类时,即使不提供标准值,程序也会以该列中位数继续计算。

这一点与前面已完成的 MAIRCA、MARCOS、MOORA、MULTIMOORA 模块都不完全相同。

3.3 Max-Min 标准化

当用户选择 min-max 时,对正向指标与适度指标,程序统一采用

$$ n_{ij}=\frac{z_{ij}-\min_i z_{ij}}{\max_i z_{ij}-\min_i z_{ij}} \tag{6} $$

对负向指标,则采用

$$ n_{ij}=\frac{\max_i x_{ij}-x_{ij}}{\max_i x_{ij}-\min_i x_{ij}} \tag{7} $$

若某列上下界相同,则程序把分母回退为 1,从而使该列标准化结果变为 0。

3.4 Z-score 后再归一化

当用户选择 z-score 时,程序先计算

$$ \hat{z}_{ij}=\frac{u_{ij}-\mu_j}{\sigma_j} \tag{8} $$

其中 \(u_{ij}\) 表示进入 z-score 之前的列值:

  • 对正向指标:\(u_{ij}=x_{ij}\);
  • 对负向指标:\(u_{ij}=x_{ij}\);
  • 对适度指标:\(u_{ij}=z_{ij}\),即式(4)处理后的值。

若第 \(j\) 个指标为负向指标,则程序先做方向翻转:

$$ \hat{z}_{ij}\leftarrow -\hat{z}_{ij} \tag{9} $$

随后再映射到 \([0,1]\) 区间:

$$ n_{ij}=\frac{\hat{z}_{ij}-\min_i \hat{z}_{ij}}{\max_i \hat{z}_{ij}-\min_i \hat{z}_{ij}} \tag{10} $$

若标准差为 0,则程序把该列标准差回退为 1。

3.5 本项目中的标准化矩阵

综合上述处理后,当前 PROMETHEE 模块实际用于后续权重计算与偏好比较的标准化矩阵记为

$$ N=(n_{ij})_{m\times n} \tag{11} $$

需要注意的是:本模块并没有像 MAIRCA、MARCOS 那样单独为熵权法构造第二套标准化矩阵,而是直接在 \(N\) 上计算熵权。

4. 权重确定

4.1 熵权法

若采用熵权法,程序直接在标准化矩阵 \(N\) 上计算权重。设第 \(j\) 个指标的列和为 \(\sum_i n_{ij}\),则其比重为

$$ p_{ij}=\frac{n_{ij}}{\sum_{k=1}^{m}n_{kj}} \tag{12} $$

熵值定义为

$$ e_j=-\frac{1}{\ln m}\sum_{i=1}^{m}p_{ij}\ln p_{ij} \tag{13} $$

差异系数定义为

$$ d_j=1-e_j \tag{14} $$

最终熵权为

$$ w_j=\frac{d_j}{\sum_{k=1}^{n}d_k} \tag{15} $$

4.2 自定义权重

若存在用户提供的自定义权重字典,程序会按所选指标顺序读取:

$$ \hat{w}=(\hat{w}_1,\hat{w}_2,\ldots,\hat{w}_n) \tag{16} $$

然后统一归一化:

$$ w_j=\frac{\hat{w}_j}{\sum_{k=1}^{n}\hat{w}_k} \tag{17} $$

如果自定义权重总和不大于 0,程序会回退为等权:

$$ w_j=\frac{1}{n} \tag{18} $$

4.3 实际分支依据是 self.weights 是否存在

这是当前模块最需要单独指出的工程实现细节之一。虽然对象中存在 weight_method 字段,UI 也会传递 entropy/custom,但在 calculate_topsis() 内部,真正决定走哪条权重路径的判断是:

  • self.weights 为真值,则走自定义权重;
  • 否则走熵权法。

因此,当前代码中 weight_method 更多是参数记录和复现脚本使用口径,而不是核心分支判断的唯一依据。

5. 偏好函数

5.1 指标差值

对任意两个方案 \(A_a\) 与 \(A_b\),在标准化矩阵 \(N\) 上定义第 \(j\) 个指标的差值为

$$ \Delta_j(a,b)=n_{aj}-n_{bj} \tag{19} $$

只有当 \(\Delta_j(a,b)>0\) 时,程序才认为 \(A_a\) 在该指标上对 \(A_b\) 具有正偏好;若 \(\Delta_j(a,b)\le 0\),则该指标对成对偏好贡献记为 0。

5.2 Usual 偏好函数

当选择 usual 时,偏好函数定义为

$$ H_j(a,b)= \begin{cases} 1, & \Delta_j(a,b)>0\\ 0, & \Delta_j(a,b)\le 0 \end{cases} \tag{20} $$

5.3 U-shape 偏好函数

当选择 u-shape 时,设阈值为 \(q\),则

$$ H_j(a,b)= \begin{cases} 0, & \Delta_j(a,b)\le q\\ 1, & \Delta_j(a,b)>q \end{cases} \tag{21} $$

5.4 V-shape 偏好函数

当选择 v-shape 时,设阈值为 \(p\),则

$$ H_j(a,b)= \begin{cases} 0, & \Delta_j(a,b)\le 0\\ \dfrac{\Delta_j(a,b)}{p}, & 0<\Delta_j(a,b)<p\\ 1, & \Delta_j(a,b)\ge p \end{cases} \tag{22} $$

若 \(p\le 0\),程序会直接回退为 1。

5.5 Level 偏好函数

当选择 level 时,设 \(0\le q\le p\),则

$$ H_j(a,b)= \begin{cases} 0, & \Delta_j(a,b)\le q\\ 0.5, & q<\Delta_j(a,b)\le p\\ 1, & \Delta_j(a,b)>p \end{cases} \tag{23} $$

5.6 Linear 偏好函数

当选择 linear 时,设 \(0\le q<p\),则

$$ H_j(a,b)= \begin{cases} 0, & \Delta_j(a,b)\le q\\ \dfrac{\Delta_j(a,b)-q}{p-q}, & q<\Delta_j(a,b)<p\\ 1, & \Delta_j(a,b)\ge p \end{cases} \tag{24} $$

若 \(p-q\le 0\),程序会回退为 1。

5.7 Gaussian 偏好函数

当选择 gaussian 时,设尺度参数为 \(s>0\),则

$$ H_j(a,b)= \begin{cases} 0, & \Delta_j(a,b)\le 0\\ 1-\exp\left(-\dfrac{\Delta_j(a,b)^2}{2s^2}\right), & \Delta_j(a,b)>0 \end{cases} \tag{25} $$

若 \(s\le 0\),程序会用 1 作为回退尺度。

6. 全局偏好矩阵与流量

6.1 全局偏好指数

在得到指标权重与单指标偏好函数后,项目构造方案 \(A_a\) 相对于 \(A_b\) 的全局偏好指数:

$$ \pi(a,b)=\sum_{j=1}^{n}w_j H_j(a,b) \tag{26} $$

于是得到全局偏好矩阵

$$ \Pi=\big(\pi(a,b)\big)_{m\times m} \tag{27} $$

其中主对角线恒为 0,因为程序对 \(a=b\) 的情形直接跳过。

6.2 正流、负流与净流

设方案总数为 \(m\),则正流定义为

$$ \phi^+(a)=\frac{1}{m-1}\sum_{b\ne a}\pi(a,b) \tag{28} $$

负流定义为

$$ \phi^-(a)=\frac{1}{m-1}\sum_{b\ne a}\pi(b,a) \tag{29} $$

净流定义为

$$ \phi(a)=\phi^+(a)-\phi^-(a) \tag{30} $$

当前模块最终输出的 Flows 工作表中,phi_plusphi_minusphi 三列正对应式(28)至式(30)。

6.3 排名规则

PROMETHEE II 的最终排序依据是净流值降序:

$$ \operatorname{Rank}(A_a)=\operatorname{rank}_{\downarrow}^{\text{min}}\big(\phi(a)\big) \tag{31} $$

程序内部使用 rank(ascending=False, method="min") 生成名次,因此若出现完全相同的净流值,会采用并列最小名次。

7. 输出结构、图表与复现脚本

7.1 统一结果结构

get_results() 返回的统一结果字典主要包括:

  • raw_data:原始数据;
  • processed_data:标准化矩阵;
  • step_results:偏好矩阵与流量结果;
  • final_resultsrankingweights
  • charts:图表清单;
  • parameters:标准化方法、权重方法、偏好函数与指标设定等。

需要特别注意的是:当前 final_results 不是单一 DataFrame,而是一个字典,内部至少包含:

  • ranking
  • weights

7.2 默认输出路径与图表

save_results() 默认会在指定目录中生成:

  • PROMETHEE_results_<时间戳>.xlsx
  • charts/weights.png
  • charts/net_flow.png
  • input_snapshot.xlsx
  • repro_module/core/promethee_calculator.py
  • repro_promethee_<时间戳>.py

其中图表含义分别为:

  • weights.png:指标权重条形图;
  • net_flow.png:方案净流值 \(\phi\) 条形图。

7.3 Excel 工作表

结合当前导出逻辑,项目会写出以下工作表:

  • 参数
  • Parameters
  • Normalized
  • Weights
  • Preference
  • Flows
  • Ranking
  • 图表清单

这意味着当前 PROMETHEE 模块的 Excel 页签是中英混合风格,与前面几个算法统一使用中文页签的习惯并不完全一致。若论文写作中要对照导出表,应以这些实际页签名为准。

7.4 分层/部分指标重算

结果页 ui/results_widget.py 当前支持“部分指标重算”,调用的接口名称仍然保留为

  • calculate_partial_topsis()

但其真实功能是“仅使用所选指标重新计算一次 PROMETHEE”。需要进一步说明的是:这次重算不会把结果追加到原 Excel 工作簿,而是通过 append_layer_results() 另外生成一个新的文件:

  • PROMETHEE_layer_results_<时间戳>.xlsx

7.5 复现脚本

当前模块存在两类复现脚本来源:

  • save_results() 自动生成的复现脚本;
  • 结果页“导出复现代码”按钮再次生成的复现脚本。

无论哪一种,脚本都会记录:

  • 输入快照路径;
  • 所选指标;
  • 指标类型;
  • 标准化方式;
  • 权重方法;
  • 偏好函数类型;
  • \(p/q/s\) 参数。

基线测试还要求该脚本具备可移植性,即脚本复制到其他目录后仍能通过相对路径读取 SCRIPT_DIR / input_snapshot.* 继续运行。

8. 与项目实现一致的若干注意事项

8.1 核心接口名仍是 calculate_topsis(),但算法实际是 PROMETHEE II

这是当前模块最醒目的遗留命名问题。论文写作时应完全按 PROMETHEE 口径描述,不要因为接口名保留为 topsis 就误写成 TOPSIS。

8.2 适度指标的核心默认值会回退到中位数

UI 通常要求用户填写适度指标标准值,但核心 _normalize() 在缺失时会自动使用该列中位数。这意味着:

  • 正常界面流程下,适度指标通常有显式标准值;
  • 直接调用核心类时,即使没给标准值,也能继续计算。

8.3 权重分支更依赖 self.weights 是否存在,而不是 weight_method

当前模块的真实逻辑是“有权重字典就按自定义处理,否则按熵权法处理”。因此,若外部代码只设置了 weight_method='custom',却没有真正调用 set_weights() 传入权重,核心仍可能落回熵权法。

8.4 熵权法直接使用标准化矩阵

与 MAIRCA、MARCOS 那类“权重计算矩阵”和“主体计算矩阵”分离的算法不同,PROMETHEE 当前实现直接在 Normalized 矩阵上计算熵权。

8.5 偏好函数参数是全局统一参数

当前 \(q\)、\(p\)、\(s\) 参数不是按指标分别配置,而是对所有指标统一生效。这一点在论文中必须说明,否则很容易被误读为“各指标可独立设置偏好阈值”。

8.6 当前导出页签名并未完全中文化

例如:

  • Normalized
  • Weights
  • Preference
  • Flows
  • Ranking

这些都是英文页签名。若需要在论文附录或项目说明中引用导出表,应直接使用这些真实页签名。

9. 论文写作模板

若本文采用本项目中的 PROMETHEE 模块进行多指标综合评价,可按如下方式描述:

首先构建方案-指标原始决策矩阵,并依据指标属性将指标划分为正向指标、负向指标和适度指标。对原始数据进行标准化处理后,采用熵权法或自定义方式确定各指标权重。随后,对任意两个方案在各指标上的差异构造偏好函数,并计算方案间的全局偏好指数矩阵;在此基础上分别求得各方案的正流、负流和净流。最后,以净流值作为 PROMETHEE II 的综合评价依据,按照净流值由大到小完成排序。

若研究需要更贴合当前软件实现,还可补充说明:

在偏好函数设定上,采用统一的偏好函数类型及其阈值参数对全部指标同时生效;对于适度指标,若未显式给定目标值,则以该指标样本中位数作为默认目标值参与标准化处理。

10. 与代码实现的对应关系

表 1 PROMETHEE 关键公式与项目实现对应关系

内容 数学表达 项目实现
原始输入结构与参数流程 式(1)—式(3) ui/upload_widget.pyui/methods_widget.pyui/main_window.py
适度指标与标准化 式(4)—式(11) core/promethee_calculator.py::_normalize
熵权法与自定义权重 式(12)—式(18) core/promethee_calculator.py::_entropy_weightsset_weightscalculate_topsis
偏好函数 式(19)—式(25) core/promethee_calculator.py::_pref_value
全局偏好矩阵与流量 式(26)—式(31) core/promethee_calculator.py::_preference_matrixcalculate_topsis
Excel、图表、部分指标重算与复现脚本 第 7 节 core/promethee_calculator.py::save_resultsappend_layer_resultsui/results_widget.py

总体来看,本项目中的 PROMETHEE 属于“统一偏好函数 + 标准化矩阵熵权/自定义赋权 + 全局偏好矩阵 + 净流值排序”的工程化实现。论文写作时,建议把式(19)—式(31)作为方法主体,再结合式(4)—式(18)说明软件在适度指标、权重生成和参数共享方式上的具体实现口径。

11. 论文模板补充

11.1 方法描述模板

“本文采用 PROMETHEE 方法对候选方案进行多指标综合评价。首先对原始决策矩阵执行指标类型处理、标准化与权重确定;随后对任意两个方案在各指标上的差异构造偏好函数,并计算全局偏好指数矩阵;最后分别求得各方案的正流、负流与净流值,并依据净流值完成排序。”

11.2 结果解释模板

结果部分可写为:结果表明,正流越大说明方案在与其他方案比较时更常处于优势,负流越大则说明其更常处于劣势,净流值综合反映方案整体优劣。若某方案净流值显著高于其他方案,则说明其在全局偏好关系中具有明显优势;若相邻方案净流值接近,则需要结合偏好函数参数与具体指标贡献做进一步解释。

11.3 表格标题模板

  1. 表 1 PROMETHEE 指标类型、偏好函数与权重设置表
  2. 表 2 PROMETHEE 全局偏好矩阵结果表
  3. 表 3 PROMETHEE 正流、负流与净流值结果表
  4. 表 4 PROMETHEE 综合排序结果表

11.4 图表题注模板

  1. 图 1 PROMETHEE 指标权重分布图。
  2. 图 2 PROMETHEE 净流值排序图。
  3. 图 3 PROMETHEE 部分指标重算结果对比图。

11.5 表格示例

表 1 PROMETHEE 排序结果表示例

方案 正流 \(\phi^+\) 负流 \(\phi^-\) 净流 \(\phi\) 排名
\(A_1\)
\(A_2\)

表注:方案排序按净流值降序确定,净流值越大表示综合表现越优。

12. 单篇终审补充

12.1 图题与表题对齐建议

  • 参数 表可写为:表X PROMETHEE 参数设置表。
  • Parameters 表可写为:表X PROMETHEE 英文参数表。
  • Normalized 表可写为:表X PROMETHEE 标准化矩阵表。
  • Weights 表可写为:表X PROMETHEE 指标权重表。
  • Preference 表可写为:表X PROMETHEE 全局偏好矩阵表。
  • Flows 表可写为:表X PROMETHEE 正流、负流与净流值表。
  • Ranking 表可写为:表X PROMETHEE 排名结果表。
  • 图表清单 表可写为:表X PROMETHEE 图表索引与路径表。
  • weights.png 建议写为:图X PROMETHEE 指标权重图。
  • net_flow.png 建议写为:图X PROMETHEE 净流值图。

12.2 终审说明

  • 当前代表性结果目录可采用 results/manual_check_20260321_01。其中主工作簿为 PROMETHEE_results_20260321_050232.xlsx
  • 当前真实工作表为 参数/Parameters/Normalized/Weights/Preference/Flows/Ranking/图表清单。这里同时存在中文 参数 和英文 Parameters,论文终稿应固定采用一种表题口径,不要混写。
  • 当前稳定实体图文件为 charts/weights.pngcharts/net_flow.png。正文若解释净流值排序,应把 Flows 工作表与 net_flow.png 配套说明。
  • 真实 repro 脚本为 repro_promethee_20260321_050232.py,并通过 SRC_FILE = SCRIPT_DIR / 'input_snapshot.xlsx' 读取脚本同目录输入快照,再输出到 repro_outputs/。它不是统一的 repro_inputs/... 结构。
  • 当前结果目录保留了多层 repro_outputs/ 复现结果。论文正文若只陈述主实验,应固定使用首层结果,不要把后续复现层混入主文。

12.3 全量强化补充

  • 本轮按真实磁盘再次核对,算法目录为 具体的算法3/多指标评价/PROMETHEE-偏好排序法,代表性结果目录为 具体的算法3/多指标评价/PROMETHEE-偏好排序法/results/manual_check_20260321_01
  • 该目录主工作簿为 PROMETHEE_results_20260321_050232.xlsx,真实工作表为 参数ParametersNormalizedWeightsPreferenceFlowsRanking图表清单。同目录还保留 input_snapshot.xlsx,其用途是复现输入快照,而不是主结果的一部分。
  • 当前主图目录为 charts/,实体图为 weights.pngnet_flow.png。因此这篇的论文主图应优先围绕指标权重和净流值排序展开。
  • 当前 repro 脚本为 repro_promethee_20260321_050232.py,脚本中明确写有 SRC_FILE = SCRIPT_DIR / 'input_snapshot.xlsx'。这说明它属于“脚本同目录输入快照 + repro_outputs”的复现结构,而不是标准 repro_inputs/... 结构。
  • repro_outputs/ 下已经实际生成多轮结果,如 PROMETHEE_results_20260321_050233.xlsxPROMETHEE_results_20260321_050319.xlsx,以及更深层 repro_outputs/repro_outputs/PROMETHEE_results_20260329_132948.xlsx。论文正文必须固定引用首层主结果,不应把这些后续复现层当作多次独立实验。
  • 这篇还应明确 repro_module/ 的存在,说明结果包中带有用于离线复现的最小模块副本;但论文里无需展开该工程细节,只需说明可复现性证据来自首层主结果目录即可。

13. 软件实现核查补充(2026-07)

  • 当前主结果目录应写作 具体的算法3/多指标评价/PROMETHEE-偏好排序法/results/manual_check_20260321_01
  • 正文应围绕 参数ParametersNormalizedWeightsPreferenceFlowsRanking图表清单 来写。
  • 图证应对应 weights.pngnet_flow.png,并把净流值 \(\phi\) 与排序结果配套说明。
  • 复现脚本应按 repro_promethee_20260321_050232.py + input_snapshot.xlsx 的口径说明;repro_outputs/ 里的后续结果只能作为递归复现证据。