PROMETHEE-偏好排序法
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_plusphi_minusphirank
其中 净流值 \(\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 的标准流程为:
- 上传数据;
- 选择参与计算的指标;
- 为每个指标设定类型;
- 在方法页选择标准化方式、权重方式和偏好函数;
- 结果页调用
calculate_topsis()完成 PROMETHEE II 计算并导出结果。
当前方法页 ui/methods_widget.py 提供的参数包括:
normalization:min-max或z-score;weight_method:entropy或custom;pref_function:usual、u-shape、v-shape、level、linear、gaussian;pref_q、pref_p、pref_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_plus、phi_minus 与 phi 三列正对应式(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_results:ranking与weights;charts:图表清单;parameters:标准化方法、权重方法、偏好函数与指标设定等。
需要特别注意的是:当前 final_results 不是单一 DataFrame,而是一个字典,内部至少包含:
rankingweights
7.2 默认输出路径与图表
save_results() 默认会在指定目录中生成:
PROMETHEE_results_<时间戳>.xlsxcharts/weights.pngcharts/net_flow.pnginput_snapshot.xlsxrepro_module/core/promethee_calculator.pyrepro_promethee_<时间戳>.py
其中图表含义分别为:
weights.png:指标权重条形图;net_flow.png:方案净流值 \(\phi\) 条形图。
7.3 Excel 工作表
结合当前导出逻辑,项目会写出以下工作表:
参数ParametersNormalizedWeightsPreferenceFlowsRanking图表清单
这意味着当前 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 当前导出页签名并未完全中文化
例如:
NormalizedWeightsPreferenceFlowsRanking
这些都是英文页签名。若需要在论文附录或项目说明中引用导出表,应直接使用这些真实页签名。
9. 论文写作模板
若本文采用本项目中的 PROMETHEE 模块进行多指标综合评价,可按如下方式描述:
首先构建方案-指标原始决策矩阵,并依据指标属性将指标划分为正向指标、负向指标和适度指标。对原始数据进行标准化处理后,采用熵权法或自定义方式确定各指标权重。随后,对任意两个方案在各指标上的差异构造偏好函数,并计算方案间的全局偏好指数矩阵;在此基础上分别求得各方案的正流、负流和净流。最后,以净流值作为 PROMETHEE II 的综合评价依据,按照净流值由大到小完成排序。
若研究需要更贴合当前软件实现,还可补充说明:
在偏好函数设定上,采用统一的偏好函数类型及其阈值参数对全部指标同时生效;对于适度指标,若未显式给定目标值,则以该指标样本中位数作为默认目标值参与标准化处理。
10. 与代码实现的对应关系
表 1 PROMETHEE 关键公式与项目实现对应关系
| 内容 | 数学表达 | 项目实现 |
|---|---|---|
| 原始输入结构与参数流程 | 式(1)—式(3) | ui/upload_widget.py、ui/methods_widget.py、ui/main_window.py |
| 适度指标与标准化 | 式(4)—式(11) | core/promethee_calculator.py::_normalize |
| 熵权法与自定义权重 | 式(12)—式(18) | core/promethee_calculator.py::_entropy_weights、set_weights、calculate_topsis |
| 偏好函数 | 式(19)—式(25) | core/promethee_calculator.py::_pref_value |
| 全局偏好矩阵与流量 | 式(26)—式(31) | core/promethee_calculator.py::_preference_matrix、calculate_topsis |
| Excel、图表、部分指标重算与复现脚本 | 第 7 节 | core/promethee_calculator.py::save_results、append_layer_results、ui/results_widget.py |
总体来看,本项目中的 PROMETHEE 属于“统一偏好函数 + 标准化矩阵熵权/自定义赋权 + 全局偏好矩阵 + 净流值排序”的工程化实现。论文写作时,建议把式(19)—式(31)作为方法主体,再结合式(4)—式(18)说明软件在适度指标、权重生成和参数共享方式上的具体实现口径。
11. 论文模板补充
11.1 方法描述模板
“本文采用 PROMETHEE 方法对候选方案进行多指标综合评价。首先对原始决策矩阵执行指标类型处理、标准化与权重确定;随后对任意两个方案在各指标上的差异构造偏好函数,并计算全局偏好指数矩阵;最后分别求得各方案的正流、负流与净流值,并依据净流值完成排序。”
11.2 结果解释模板
结果部分可写为:结果表明,正流越大说明方案在与其他方案比较时更常处于优势,负流越大则说明其更常处于劣势,净流值综合反映方案整体优劣。若某方案净流值显著高于其他方案,则说明其在全局偏好关系中具有明显优势;若相邻方案净流值接近,则需要结合偏好函数参数与具体指标贡献做进一步解释。
11.3 表格标题模板
- 表 1 PROMETHEE 指标类型、偏好函数与权重设置表
- 表 2 PROMETHEE 全局偏好矩阵结果表
- 表 3 PROMETHEE 正流、负流与净流值结果表
- 表 4 PROMETHEE 综合排序结果表
11.4 图表题注模板
- 图 1 PROMETHEE 指标权重分布图。
- 图 2 PROMETHEE 净流值排序图。
- 图 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.png与charts/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,真实工作表为参数、Parameters、Normalized、Weights、Preference、Flows、Ranking、图表清单。同目录还保留input_snapshot.xlsx,其用途是复现输入快照,而不是主结果的一部分。 - 当前主图目录为
charts/,实体图为weights.png与net_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.xlsx、PROMETHEE_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。 - 正文应围绕
参数、Parameters、Normalized、Weights、Preference、Flows、Ranking、图表清单来写。 - 图证应对应
weights.png与net_flow.png,并把净流值 \(\phi\) 与排序结果配套说明。 - 复现脚本应按
repro_promethee_20260321_050232.py + input_snapshot.xlsx的口径说明;repro_outputs/里的后续结果只能作为递归复现证据。