ELECTRE-超排序法
ELECTRE(ELimination Et Choix Traduisant la REalité,超排序法)是一类基于优势关系判定的多指标决策方法。其核心思想不是直接计算“到理想解的距离”,而是通过一致性指标与非一致性指标判断“方案 Ai 是否能够超越方案 Aj”,再由超越…
ELECTRE-超排序法
1. 方法概述
ELECTRE(ELimination Et Choix Traduisant la REalité,超排序法)是一类基于优势关系判定的多指标决策方法。其核心思想不是直接计算“到理想解的距离”,而是通过一致性指标与非一致性指标判断“方案 \(A_i\) 是否能够超越方案 \(A_j\)”,再由超越关系得到最终排序。
就本项目的具体实现而言,当前模块采用的是一种 ELECTRE I 风格的超排序实现,并在结果阶段加入了净流排序口径:
- 指标类型支持正向指标、负向指标与适度指标;
- 支持
min-max与z-score两种标准化方式; - 权重支持熵权法与自定义权重;
- 通过一致性矩阵
Concordance、非一致性矩阵Discordance与阈值 \((c^\ast,d^\ast)\) 构造Outranking矩阵; - 最终不是提取经典 ELECTRE I 的核集,而是计算超排序矩阵的流出强度、流入强度和净流 \(\phi\) 进行排序。
需要特别说明的是:虽然核心接口沿用了 calculate_topsis()、calculate_partial_topsis() 这样的历史命名,UI 中部分槽函数名也仍保留 topsis 字样,但当前实际执行的算法是 core/electre_calculator.py 中的 ELECTRE 计算流程,而不是 TOPSIS。
设共有 \(m\) 个方案、\(n\) 个指标,原始决策矩阵记为
$$ X=(x_{ij})_{m\times n}, \quad i=1,2,\ldots,m, \quad j=1,2,\ldots,n \tag{1} $$
其中 \(x_{ij}\) 表示方案 \(A_i\) 在指标 \(C_j\) 上的原始观测值。
设指标权重向量为
$$ 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} $$
项目最终导出的 Scores 表与 Ranking 表,就是在式(1)和式(2)基础上,通过超排序关系矩阵进一步得到的结果。
2. 输入结构、指标类型与预处理
2.1 输入文件结构
当前上传页 ui/upload_widget.py 支持 .xlsx、.xls 与 .csv 文件。结合 utils/data_validator.py,项目要求输入数据满足:
- 第 1 列为方案名称;
- 第 2 列及之后为指标列;
- 指标列必须全部可转为数值;
- 指标列不允许空值;
- 方案名称不允许重复;
- 上传页默认不允许常数列。
因此,项目进入核心计算器 ELECTRECalculator 的数据结构可视为“首列方案名、其余列为数值型指标”的标准方案-指标矩阵。若研究者直接调用核心类而绕过界面,则即使存在常数列,核心标准化函数也仍会给出数值结果,只是该列通常会退化为全 0 列。
2.2 指标类型与适度指标处理
当前模块支持三类指标:
- 正向指标:值越大越优;
- 负向指标:值越小越优;
- 适度指标:越接近给定标准值越优。
设第 \(j\) 个适度指标的标准值为 \(s_j^\ast\)。当前实现不是采用“按最大偏差归一”的适度指标转换,而是先做如下线性偏差变换:
$$ v_{ij}= \begin{cases} 1-\left|x_{ij}-s_j^\ast\right|, & C_j \text{ 为适度指标}\\[4pt] x_{ij}, & C_j \text{ 为正向或负向指标} \end{cases} \tag{3} $$
式(3)对应 ELECTRECalculator._normalize() 中
col = 1.0 - np.abs(col - target)
这一实际实现。完成式(3)后,适度指标在后续标准化与一致性判断中统一按“效益越大越好”的方向参与计算。
3. 标准化方法与权重确定
3.1 Max-Min 标准化
当用户选择 min-max 时,若第 \(j\) 个指标为正向指标或适度指标,则程序采用
$$ n_{ij}=\frac{v_{ij}-\min_i v_{ij}}{\max_i v_{ij}-\min_i v_{ij}} \tag{4} $$
若第 \(j\) 个指标为负向指标,则采用
$$ n_{ij}=\frac{\max_i v_{ij}-v_{ij}}{\max_i v_{ij}-\min_i v_{ij}} \tag{5} $$
当某列满足 \(\max_i v_{ij}=\min_i v_{ij}\) 时,核心代码会把分母替换为 1,因此该列标准化结果最终为全 0,而不是报错。
3.2 Z-score 标准化后再映射到 \([0,1]\)
当用户选择 z-score 时,程序先按方向做标准分数变换。对正向指标和适度指标,有
$$ z_{ij}=\frac{v_{ij}-\mu_j}{\sigma_j} \tag{6} $$
对负向指标,有
$$ z_{ij}=\frac{\mu_j-v_{ij}}{\sigma_j} \tag{7} $$
其中 \(\mu_j\) 和 \(\sigma_j\) 分别表示第 \(j\) 列的均值与标准差。若 \(\sigma_j\le 10^{-12}\),程序会将其替换为 1 作为兜底分母。随后,项目再把 \(z_{ij}\) 映射到 \([0,1]\) 区间:
$$ n_{ij}=\frac{z_{ij}-\min_i z_{ij}}{\max_i z_{ij}-\min_i z_{ij}} \tag{8} $$
若 \(\max_i z_{ij}=\min_i z_{ij}\),则该列同样退化为全 0。
经过上述处理后,项目真正参与 ELECTRE 一致性和非一致性计算的标准化矩阵记为
$$ N=(n_{ij})_{m\times n} \tag{9} $$
3.3 熵权法
若用户选择 entropy,项目直接基于标准化矩阵 \(N\) 计算熵权。首先定义列内比重
$$ p_{ij}=\frac{n_{ij}}{\sum_{k=1}^{m}n_{kj}} \tag{10} $$
若某列列和不大于 0,则程序会把该列概率向量直接改为等概率 \(1/m\)。随后计算熵值
$$ e_j=-\frac{1}{\ln m}\sum_{i=1}^{m}p_{ij}\ln p_{ij} \tag{11} $$
差异系数定义为
$$ d_j=1-e_j \tag{12} $$
最终权重为
$$ w_j=\frac{d_j}{\sum_{k=1}^{n}d_k} \tag{13} $$
若所有 \(d_j\le 0\),项目会退化为等权向量。
3.4 自定义权重
若用户选择 custom,权重并不在方法页直接编辑,而是跳转到独立页面 ui/weight_editor_widget.py。该页面每页显示 10 个指标,支持:
- 手工录入权重;
- 当前页归一化;
- 全部指标平均分配权重;
- 保存时若全局权重和不约等于 1,则提示是否自动归一化。
设用户录入的原始权重为 \(\hat{w}_j\),则项目在实际计算当前选中指标子集时,会再次按所选指标重新对齐,并做归一化:
$$ w_j=\frac{\hat{w}_j}{\sum_{k=1}^{n}\hat{w}_k} \tag{14} $$
因此,不论是整体分析还是部分指标重算,最终进入 Concordance 计算的权重向量始终满足式(2)。
4. 一致性矩阵、非一致性矩阵与超排序关系
4.1 一致性矩阵
在标准化矩阵 \(N\) 上,项目把所有指标都统一转成“越大越好”的方向,因此对任意两个方案 \(A_i\) 与 \(A_j\),一致性指标直接按“有多少权重支持 \(A_i\) 不差于 \(A_j\)”来计算:
$$ C_{ij}=\sum_{k:\,n_{ik}\ge n_{jk}} w_k, \quad i\ne j \tag{15} $$
并令
$$ C_{ii}=0 \tag{16} $$
式(15)与 ELECTRECalculator._compute_concordance() 的实际实现一致。需要注意的是,该函数虽然保留了 typ 形参,但当前代码中并未再单独使用指标类型,而是完全依赖前面的标准化步骤把各列方向统一为效益型。
4.2 非一致性矩阵
项目以列极差作为归一尺度。对第 \(k\) 个指标,定义
$$ R_k=\max_i n_{ik}-\min_i n_{ik} \tag{17} $$
若 \(R_k<10^{-12}\),则程序将其替换为 1。随后,对任意 \(i\ne j\),非一致性指标定义为
$$ D_{ij}=\max_{1\le k\le n}\frac{\max\left(0,\ n_{jk}-n_{ik}\right)}{R_k} \tag{18} $$
式(18)表示:只关注那些 \(A_j\) 明显优于 \(A_i\) 的指标差距,并取其中最大的相对劣势作为非一致性强度。
4.3 阈值与超排序矩阵
当前方法页 ui/methods_widget.py 默认给出:
- 一致性阈值 \(c^\ast=0.6\)
- 非一致性阈值 \(d^\ast=0.4\)
若用户输入的阈值超出 \([0,1]\) 区间,核心代码会退回到矩阵均值,即分别以 mean(C) 和 mean(D) 作为阈值。
在此基础上,项目按如下规则生成超排序矩阵 \(S=(s_{ij})\):
$$ s_{ij}= \begin{cases} 1, & C_{ij}\ge c^\ast \ \text{且}\ D_{ij}\le d^\ast,\ i\ne j\\[4pt] 0, & \text{其他} \end{cases} \tag{19} $$
并令 \(s_{ii}=0\)。这对应 ELECTRECalculator._outranking() 的实际实现。
5. 净流得分与排序口径
5.1 流出强度与流入强度
与经典 ELECTRE I 常见的“核集提取”不同,本项目在得到超排序矩阵 \(S\) 后,进一步计算每个方案的流出强度与流入强度。设共有 \(m\) 个方案,则
$$ \phi_i^{+}=\frac{1}{m-1}\sum_{j=1}^{m}s_{ij} \tag{20} $$
$$ \phi_i^{-}=\frac{1}{m-1}\sum_{j=1}^{m}s_{ji} \tag{21} $$
其中 \(\phi_i^{+}\) 表示方案 \(A_i\) 超越其他方案的比例,\(\phi_i^{-}\) 表示方案 \(A_i\) 被其他方案超越的比例。
5.2 净流与最终排序
项目进一步定义净流得分为
$$ \phi_i=\phi_i^{+}-\phi_i^{-} \tag{22} $$
并按 \(\phi_i\) 降序排序:
$$ \operatorname{Rank}(A_i)=\operatorname{rank}_{\downarrow}^{\text{min}}(\phi_i) \tag{23} $$
这里的 min 表示并列时取最小名次。例如两个方案并列第 1,则下一名次为第 3,而不是第 2。这与 scores_df["phi"].rank(ascending=False, method="min") 的实现一致。
因此,本项目最终导出的 Scores 表包含:
alternativephi_plusphi_minusphirank
其中真正用于排序的是 phi,而不是传统 ELECTRE 文献中常见的核集成员标识。
6. 项目输出结构与扩展功能
6.1 实际主流程与结果导出
虽然目录中还保留了 utils/data_processor.py、utils/excel_handler.py 等较早期工具代码,但当前主窗口 ui/main_window.py 实际调用的是 core/electre_calculator.py。因此,若论文需要复现软件实际输出,应以 ELECTRECalculator.calculate_topsis() 与 save_results() 的行为为准。
结果页在每次计算完成后,首先创建目录:
results/ELECTRE-超排序法分析结果_<时间戳>/
随后 save_results() 会在其下再创建一层结果目录:
ELECTRE结果_<时间戳>/ELECTRE结果_<时间戳>.xlsx
因此,最终 Excel 的实际路径通常为
results/ELECTRE-超排序法分析结果_<时间戳>/ELECTRE结果_<时间戳>/ELECTRE结果_<时间戳>.xlsx
6.2 Excel、图表与复现脚本
当前结果文件默认包含以下工作表:
ParametersNormalizedWeightsConcordanceDiscordanceOutrankingScoresRankingCharts(图表生成成功时出现)
其中:
Parameters记录normalization、weight_method、concordance_threshold、discordance_threshold;Normalized对应标准化矩阵 \(N\);Weights对应权重向量;Concordance、Discordance、Outranking分别对应式(15)、式(18)、式(19);Scores对应式(20)—式(23)的完整结果;Ranking只保留方案名与排名;Charts记录生成图表的名称与路径。
程序会同时输出两张图:
..._weights_bar.png:指标权重条形图;..._phi_bar.png:净流 \(\phi\) 条形图。
此外,save_results() 还会自动生成:
repro_inputs/input_snapshot_<时间戳>.csvrepro_electre_<时间戳>.py
结果页中的“导出复现代码”按钮也可以再次在同目录生成一份复现脚本,便于单独交付论文附录或项目复算说明。
6.3 部分指标重算
当前结果页支持“分层计算”或“部分指标重算”。其实现方式是:
- 先完成一次整体 ELECTRE 计算;
- 在结果页勾选部分指标;
- 调用
calculate_partial_topsis(indicators)对该指标子集重新计算; - 若使用自定义权重,则自动对所选子集权重重新截取并归一化;
- 将结果另存为
ELECTRE分层结果_<时间戳>.xlsx。
与部分算法“把子集结果追加到原工作簿”不同,本模块的分层计算会新建一个完整 Excel 文件,并写出与主结果同结构的工作表集合。
7. 与项目实现一致的若干注意事项
7.1 这是 ELECTRE I 风格超排序 + 净流排序,不是经典核集输出
如果只从算法名称出发,容易默认结果应当是“超越核”或“支配子集”。但当前项目实际上是先构造 ELECTRE I 风格的超排序矩阵,再用式(20)—式(23)的净流进行排序。因此,论文若直接引用软件结果,应明确说明采用的是“基于超排序矩阵净流的 ELECTRE 排序口径”。
7.2 适度指标转换口径较为简化
本项目对适度指标采用的是式(3)这一简单偏差变换,而不是按最大偏差或目标区间进一步归一的常见写法。随后还会经过 min-max 或 z-score 标准化,因此若论文需要精确复现实验,应优先写出式(3)而不要套用其他资料中的适度指标变换公式。
7.3 界面层不允许适度指标标准值为 0
ui/indicators_widget.py 当前会把适度指标标准值等于 0 视为“未填写”,因此通过正常界面流程时,适度指标目标值必须是非 0 数值。需要注意的是,核心代码本身并不禁止 0;这是 UI 约束与核心能力之间的实现差异。
7.4 常数列在界面层会被拦截,但核心会退化为全 0 列
上传页校验默认拒绝常数列;但若绕过界面直接调用 ELECTRECalculator,则标准化阶段会把常数列映射为 0,并继续完成后续计算。因此,在复现实验时,最好说明数据是通过界面导入,还是直接通过 Python 调用核心类导入。
8. 论文写作模板
若本文采用本项目中的 ELECTRE 模块进行方案排序,可按如下方式描述:
首先构建方案-指标决策矩阵,并依据指标属性将指标划分为正向指标、负向指标和适度指标。对适度指标先根据其与目标值的偏离程度做效益化转换,随后采用 Max-Min 标准化或 Z-score 标准化将各指标统一映射到无量纲区间。进一步结合熵权法或专家给定权重,计算任意两个方案之间的一致性指标和非一致性指标,并依据给定的一致性阈值与非一致性阈值构造超排序关系矩阵。最后根据超排序矩阵计算各方案的流出强度、流入强度和净流值,并据此完成方案排序。
若本文采用的是部分指标重算功能,还可补充说明:
在整体超排序结果基础上,本文进一步选取部分核心指标重新构造超排序矩阵,并比较子集评价结果与全指标结果的差异,以检验排序稳定性。
9. 与代码实现的对应关系
表 1 ELECTRE 关键公式与项目实现对应关系
| 内容 | 数学表达 | 项目实现 |
|---|---|---|
| 原始输入结构与权重向量 | 式(1)—式(2) | ui/upload_widget.py、utils/data_validator.py、core/electre_calculator.py::set_data |
| 适度指标偏差变换 | 式(3) | core/electre_calculator.py::_normalize |
| 两种标准化方式 | 式(4)—式(9) | core/electre_calculator.py::_normalize、ui/methods_widget.py |
| 熵权法与自定义权重 | 式(10)—式(14) | core/electre_calculator.py::_entropy_weights、ui/weight_editor_widget.py |
| 一致性矩阵 | 式(15)—式(16) | core/electre_calculator.py::_compute_concordance |
| 非一致性矩阵 | 式(17)—式(18) | core/electre_calculator.py::_compute_discordance |
| 超排序矩阵 | 式(19) | core/electre_calculator.py::_outranking |
| 净流得分与排序 | 式(20)—式(23) | core/electre_calculator.py::calculate_topsis |
| Excel、图表、复现脚本与部分指标重算 | 第 6 节 | core/electre_calculator.py::save_results、append_layer_results、ui/results_widget.py |
总体来看,本项目中的 ELECTRE 属于“保留 ELECTRE I 超排序主线,同时扩展标准化方式、权重来源、图表导出、复现脚本和净流排序”的工程化实现。对论文写作而言,建议把式(15)—式(23)作为方法主体,再结合式(3)—式(14)说明当前软件在适度指标处理、标准化和赋权环节的具体口径。
10. 论文模板补充
10.1 方法描述模板
“本文采用 ELECTRE 超排序方法对候选方案进行比较。首先对原始决策矩阵执行指标类型处理、标准化与权重确定,随后分别计算方案间的一致性指标与非一致性指标,并在给定阈值约束下构造超排序关系矩阵。最后根据流出强度、流入强度与净流值对方案进行排序和解释。”
10.2 结果解释模板
结果部分可写为:结果表明,一致性越高、非一致性越低的方案对之间更容易形成超排序关系。若某方案的净流值较大,说明其在整体比较中更常处于优势地位;若净流值较小或为负,则说明其在多数成对比较中处于劣势。
10.3 表格标题模板
- 表 1 ELECTRE 参数与阈值设置表
- 表 2 ELECTRE 一致性矩阵与非一致性矩阵结果表
- 表 3 ELECTRE 超排序矩阵与净流值结果表
- 表 4 ELECTRE 综合排序结果表
10.4 图表题注模板
- 图 1 ELECTRE 净流值排序图。
- 图 2 ELECTRE 超排序关系可视化图。
- 图 3 ELECTRE 部分指标重算结果对比图。
10.5 表格示例
表 1 ELECTRE 排序结果表示例
| 方案 | 流出强度 | 流入强度 | 净流值 | 排名 |
|---|---|---|---|---|
| \(A_1\) | ||||
| \(A_2\) |
表注:净流值越大表示方案整体优势越强,最终排序由净流值降序确定。
11. 单篇终审补充
11.1 图题与表题对齐建议
Parameters表可写为:表X ELECTRE 参数设置表。Normalized表可写为:表X ELECTRE 标准化矩阵表。Weights表可写为:表X ELECTRE 指标权重表。Concordance表可写为:表X ELECTRE 一致性矩阵表。Discordance表可写为:表X ELECTRE 非一致性矩阵表。Outranking表可写为:表X ELECTRE 超排序矩阵表。Scores表可写为:表X ELECTRE 流出强度、流入强度与净流值表。Ranking表可写为:表X ELECTRE 排名结果表。Charts表可写为:表X ELECTRE 图表索引表。*_weights_bar.png建议写为:图X ELECTRE 指标权重图。*_phi_bar.png建议写为:图X ELECTRE 净流值排序图。
11.2 终审说明
- 当前代表性结果目录可采用
results/__codex_electre_direct_run_20260321/ELECTRE结果_20260321_041421。其中主工作簿为ELECTRE结果_20260321_041421.xlsx。 - 当前真实工作表为
Parameters/Normalized/Weights/Concordance/Discordance/Outranking/Scores/Ranking/Charts。论文表题应按这组英文 sheet 名落地。 - 当前稳定实体图文件为
ELECTRE结果_20260321_041421_weights_bar.png与ELECTRE结果_20260321_041421_phi_bar.png。图文件不在charts/子目录,而是直接与结果簿同级存放,这一点在附录文件说明中应写清。 - 真实 repro 脚本为
repro_electre_20260321_041421.py,并通过INPUT_FILE = Path('repro_inputs/input_snapshot_20260321_041421.csv')读取输入快照。附录中的复现实验说明应保持这一repro_inputs/...csv相对路径口径。 - 当前结果目录会在
repro_outputs/results_时间戳/下继续生成复现结果。正文若只陈述主实验,应固定引用首层结果目录,避免把后续复现输出的图和表混入主实验章节。
11.3 全量强化补充
- 本轮按真实磁盘再次核对,算法目录为
具体的算法3/多指标评价/ELECTRE-超排序法,代表性结果目录为具体的算法3/多指标评价/ELECTRE-超排序法/results/__codex_electre_direct_run_20260321/ELECTRE结果_20260321_041421。 - 该目录主工作簿为
ELECTRE结果_20260321_041421.xlsx,真实工作表为Parameters、Normalized、Weights、Concordance、Discordance、Outranking、Scores、Ranking、Charts。 - 当前实体图并非放在
charts/子目录,而是与主工作簿同级直接存放:ELECTRE结果_20260321_041421_weights_bar.png与ELECTRE结果_20260321_041421_phi_bar.png。这点必须在附录里写清,否则很容易按其他算法的charts/惯例写错。 - 当前 repro 脚本为
repro_electre_20260321_041421.py,并通过INPUT_FILE = Path('repro_inputs/input_snapshot_20260321_041421.csv')读取输入快照;该输入副本在repro_inputs/中实际存在。 - 目录下还保留
repro_outputs/results_20260321_041422/ELECTRE结果_20260321_041422/的首层复现结果,并继续可递归生成更深层结果。论文与交付清单应只把首层目录ELECTRE结果_20260321_041421作为主实验证据,后续层仅作为复现链说明。 results/__codex_electre_direct_run_20260321本身只是外层聚合目录,不应被误写成单次结果目录;真正可引用的是其内层时间戳结果目录。
12. 软件实现核查补充(2026-07)
- 当前实现的主结果目录应写作
具体的算法3/多指标评价/ELECTRE-超排序法/results/__codex_electre_direct_run_20260321/ELECTRE结果_20260321_041421,主工作簿以ELECTRE结果_20260321_041421.xlsx为准。 - 正文应围绕
Parameters、Normalized、Weights、Concordance、Discordance、Outranking、Scores、Ranking、Charts来写。 - 图证应对应
ELECTRE结果_20260321_041421_weights_bar.png与ELECTRE结果_20260321_041421_phi_bar.png,并说明图文件与工作簿同级而不是在charts/子目录。 repro_electre_20260321_041421.py + repro_inputs/input_snapshot_20260321_041421.csv是标准repro_inputs复现口径,后续repro_outputs/产物只能作为再生成证据。