EDAS-基于平均解距离评价法
EDAS(Evaluation based on Distance from Average Solution,基于平均解距离评价法)是一种典型的多指标综合评价方法。其核心思想是:先为每个指标构造平均解,再分别衡量各方案相对于平均解的正距离与负距离,随后结合指标权重形成综合得分…
EDAS-基于平均解距离评价法
1. 方法概述
EDAS(Evaluation based on Distance from Average Solution,基于平均解距离评价法)是一种典型的多指标综合评价方法。其核心思想是:先为每个指标构造平均解,再分别衡量各方案相对于平均解的正距离与负距离,随后结合指标权重形成综合得分,并据此完成排序。
就本项目的具体实现而言,EDAS 模块并不是“直接套用教科书公式”,而是采用了一条明确的工程化计算链:
- 指标类型支持正向指标、负向指标与适度指标;
- 适度指标先转换为“越接近目标值越优”的效益型变量;
- 再对全部指标执行
min-max或z-score标准化; - EDAS 的平均解、PDA、NDA、综合得分均基于标准化矩阵计算,而不是直接基于原始矩阵计算;
- 权重支持熵权法与自定义权重,并支持结果页对部分指标子集再次计算。
设共有 \(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} $$
项目最终输出的 EDAS得分 与 排名,本质上就是在式(1)与式(2)基础上,经过预处理、标准化和平均解距离计算后得到的结果。
2. 输入结构、指标类型与预处理
2.1 输入文件结构
当前上传页 ui/upload_widget.py 支持 .xlsx、.xls 与 .csv 三类文件。结合 utils/data_validator.py,项目要求输入数据满足:
- 第 1 列为对象名称;
- 第 2 列及之后为指标列;
- 指标列必须全部可转为数值;
- 指标列不允许空值;
- 对象名称不允许重复;
- 上传页校验默认不允许常数列。
因此,项目实际进入计算器 core/edas_calculator.py 的数据结构可表示为
$$ \mathcal{D}=\{A_i,\ x_{i1},x_{i2},\ldots,x_{in}\}_{i=1}^{m} \tag{3} $$
其中第一个字段为对象名称,其余字段为数值型指标。若研究者绕过界面直接调用核心类,常数列虽然不会在入口处被拦截,但核心标准化函数仍保留了相应兜底逻辑。
2.2 指标类型
当前 EDAS 模块支持三类指标:
- 正向指标:值越大越优;
- 负向指标:值越小越优;
- 适度指标:越接近给定标准值越优。
设第 \(j\) 个适度指标的目标值为 \(s_j^\ast\)。项目不会为适度指标单独设计新的 EDAS 距离公式,而是先将其转换为效益型变量。具体地,对适度指标列有
$$ y_{ij}=1-\frac{|x_{ij}-s_j^\ast|}{\max\left(|\max_i x_{ij}-s_j^\ast|,\ |\min_i x_{ij}-s_j^\ast|\right)} \tag{4} $$
式(4)越接近 1,表示该方案越接近目标值。若分母为 0,即该列全部取值都与目标值重合,则项目直接将整列记为
$$ y_{ij}=1 \tag{5} $$
这对应 EDASCalculator._process_moderate_indicators() 的实际实现。完成式(4)或式(5)后,适度指标在后续步骤中统一按正向指标处理。
3. 标准化方法
3.1 统一说明
记经过适度指标处理后的矩阵为
$$ Y=(y_{ij})_{m\times n} \tag{6} $$
项目在标准化阶段使用极小常数
$$ \varepsilon=10^{-10} \tag{7} $$
以避免分母为 0。需要特别强调的是:当前项目并不是直接对原始矩阵 \(X\) 执行 EDAS,而是先对 \(Y\) 做标准化,再基于标准化结果计算平均解与距离。
3.2 Max-Min 标准化
当用户选择 min-max 时,若第 \(j\) 个指标为正向指标(以及已转化后的适度指标),则程序采用
$$ n_{ij}=\frac{y_{ij}-\min_i y_{ij}}{\max_i y_{ij}-\min_i y_{ij}+\varepsilon} \tag{8} $$
若第 \(j\) 个指标为负向指标,则采用
$$ n_{ij}=\frac{\max_i y_{ij}-y_{ij}}{\max_i y_{ij}-\min_i y_{ij}+\varepsilon} \tag{9} $$
若某列满足 \(\max_i y_{ij}=\min_i y_{ij}\),核心代码会直接把该列标准化结果记为 1。虽然上传页通常已拦截常数列,但该兜底逻辑仍真实存在于 EDASCalculator._normalize_data() 中。
3.3 Z-score 标准化后再映射到 \([0,1]\)
当用户选择 z-score 时,程序先做方向敏感的标准分数变换。对正向指标(以及已转化后的适度指标),有
$$ z_{ij}=\frac{y_{ij}-\mu_j}{\sigma_j+\varepsilon} \tag{10} $$
对负向指标,有
$$ z_{ij}=\frac{\mu_j-y_{ij}}{\sigma_j+\varepsilon} \tag{11} $$
其中 \(\mu_j\) 和 \(\sigma_j\) 分别表示第 \(j\) 列的均值与标准差。随后,项目再把 \(z_{ij}\) 按列映射到 \([0,1]\) 区间:
$$ n_{ij}=\frac{z_{ij}-\min_i z_{ij}}{\max_i z_{ij}-\min_i z_{ij}+\varepsilon} \tag{12} $$
若映射前某列满足 \(\max_i z_{ij}=\min_i z_{ij}\),则该列标准化结果直接记为 0。这一点与 min-max 情况下常数列记为 1 的兜底规则并不相同。
经过上述处理后,项目实际用于 EDAS 计算的标准化矩阵记为
$$ N=(n_{ij})_{m\times n} \tag{13} $$
4. 权重确定
4.1 熵权法
若用户选择 entropy,项目直接基于标准化矩阵 \(N\) 计算熵权。首先定义第 \(j\) 个指标在第 \(i\) 个对象上的比重为
$$ p_{ij}=\frac{n_{ij}}{\sum_{k=1}^{m}n_{kj}} \tag{14} $$
若某列列和为 0,程序会先把该列分母替换为 \(\varepsilon\) 再继续计算。随后定义熵值
$$ e_j=-\frac{1}{\ln m}\sum_{i=1}^{m}p_{ij}\ln\left(p_{ij}+\varepsilon\right) \tag{15} $$
差异系数为
$$ d_j=1-e_j \tag{16} $$
最终熵权为
$$ w_j=\frac{d_j}{\sum_{k=1}^{n}d_k} \tag{17} $$
式(14)—式(17)与 EDASCalculator._calculate_entropy_weights() 完全一致。
4.2 自定义权重
若用户选择 custom,权重不是在方法页直接录入,而是进入独立页面 ui/weight_editor_widget.py 编辑。该页面每次显示 10 个指标,支持:
- 手工录入权重;
- 平均分配全部指标权重;
- 对当前页权重归一化到 1;
- 保存时若全局权重和不约等于 1,则提示是否自动归一化。
设用户录入的原始权重为 \(\hat{w}_j\),则核心计算前会按当前选中指标重新对齐,并统一归一化为
$$ w_j=\frac{\hat{w}_j}{\sum_{k=1}^{n}\hat{w}_k} \tag{18} $$
因此,真正参与 EDAS 计算的权重向量始终与当前实际参与评价的指标集合保持一致。
5. EDAS 主体计算过程
5.1 平均解
本项目以标准化矩阵 \(N\) 为输入,按列计算平均解:
$$ AV_j=\frac{1}{m}\sum_{i=1}^{m}n_{ij} \tag{19} $$
为避免后续分母为 0,程序进一步定义稳定分母
$$ \delta_j=\max\left(|AV_j|,\ \varepsilon\right) \tag{20} $$
这对应 average_solution.replace(0, 1e-10).abs() 的实现。
5.2 正距离 PDA 与负距离 NDA
对正向指标(以及已转化后的适度指标),项目采用
$$ PDA_{ij}=\max\left(0,\ \frac{n_{ij}-AV_j}{\delta_j}\right) \tag{21} $$
$$ NDA_{ij}=\max\left(0,\ \frac{AV_j-n_{ij}}{\delta_j}\right) \tag{22} $$
对负向指标,方向反转为
$$ PDA_{ij}=\max\left(0,\ \frac{AV_j-n_{ij}}{\delta_j}\right) \tag{23} $$
$$ NDA_{ij}=\max\left(0,\ \frac{n_{ij}-AV_j}{\delta_j}\right) \tag{24} $$
这正是 EDASCalculator.calculate_edas() 中 if col_type == "负向指标" 分支的计算口径。
5.3 加权正距离与加权负距离
得到 \(PDA\) 与 \(NDA\) 后,项目按权重向量 \(w\) 计算各对象的加权正距离与加权负距离:
$$ SP_i=\sum_{j=1}^{n}w_j\,PDA_{ij} \tag{25} $$
$$ SN_i=\sum_{j=1}^{n}w_j\,NDA_{ij} \tag{26} $$
其中 \(SP_i\) 越大越好,\(SN_i\) 越小越好。
5.4 标准化正负距离、综合得分与排序
项目继续对 \(SP_i\) 与 \(SN_i\) 做极值归一化。若 \(\max_i SP_i=0\) 或 \(\max_i SN_i=0\),则分母会被替换为 \(\varepsilon\)。具体地,
$$ NSP_i=\frac{SP_i}{\max_k SP_k} \tag{27} $$
$$ NSN_i=1-\frac{SN_i}{\max_k SN_k} \tag{28} $$
最终 EDAS 综合得分定义为
$$ AS_i=\frac{NSP_i+NSN_i}{2} \tag{29} $$
项目结果表中的 EDAS得分 对应的正是式(29)。最后按 \(AS_i\) 降序排序,得到
$$ \operatorname{Rank}(A_i)=\operatorname{rank}_{\downarrow}^{\text{dense}}(AS_i) \tag{30} $$
这里的 dense 表示并列名次不留空档。例如两个对象并列第 1,则下一个名次为第 2,而不是第 3。该规则来自 scores.rank(ascending=False, method="dense").astype(int) 的实际实现。
在内存中的统一结果字典里,final_results 表包含:
- 对象名称列;
SPSNNSPNSNEDAS得分排名
这比最终 Excel 的主结果 sheet 更完整。
6. 项目输出结构与扩展功能
6.1 统一结果结构
当前主流程由 ui/main_window.py 驱动,真正的结果保存主路径是 core/edas_calculator.py::save_results(),而不是 utils/excel_handler.py 中较早期的通用导出函数。因此,若论文需要复现软件实际输出,应以 EDASCalculator 的保存逻辑为准。
calculate_edas() 返回的统一结果字典主要包括:
raw_data:原始输入数据;processed_data:标准化矩阵;step_results:平均解、PDA、NDA、SP/SN、NSP/NSN;final_results:包含SP、SN、NSP、NSN、EDAS得分、排名的结果表;charts:图表信息;parameters:标准化方法、权重方法、指标类型、所选指标、权重、适度指标标准值、源文件路径等参数。
6.2 Excel、图表与复现脚本
结果页完成计算后,会自动创建结果目录:
results/EDAS-基于平均解距离评价法分析结果_<时间戳>/
并在该目录下保存:
EDAS_results_<时间戳>.xlsxcharts/weights.pngcharts/scores.pnginput_snapshot.xlsxrepro_edas_<时间戳>.pyrepro_module/
其中 Excel 默认包含以下工作表:
参数原始数据标准化矩阵指标权重Step 1_ 平均解AVStep 2_ PDAStep 3_ NDAStep 4_ SP_SNStep 5_ NSP_NSNStep 6_ EDAS得分与排名图表清单
需要特别说明的是:
- 内存中的
final_results含有SP、SN、NSP、NSN等列; - 导出到 Excel 时,这些中间量分别拆分到
Step 4_ SP_SN与Step 5_ NSP_NSN; Step 6_ EDAS得分与排名只保留对象名称、EDAS得分与排名三列。
此外,结果页 ui/results_widget.py 还提供“导出复现代码”按钮。即使自动导出的复现脚本已存在,用户仍可在结果页再次显式导出一份脚本与输入快照。
6.3 部分指标子集的分层计算
EDAS 结果页支持对部分指标重新计算。其实现方式是:
- 先完成一次整体 EDAS 计算;
- 在结果页勾选部分指标;
- 调用
calculate_partial_edas(selected_indicators)对子集重新计算; - 若原来使用自定义权重,则对子集权重重新截取并归一化;
- 通过
append_layer_results()另存为EDAS_layer_results_<时间戳>.xlsx。
该分层结果文件默认包含:
EDAS分层评价结果指标权重平均解AVPDANDASP_SNNSP_NSN
因此,本项目不仅能输出全指标下的 EDAS 排序,也可用于论文中的指标删减分析、层次化比较分析或局部稳健性分析。
7. 与项目实现一致的若干注意事项
7.1 本项目以标准化矩阵而不是原始矩阵计算 EDAS
这是当前实现最重要的口径之一。很多 EDAS 文献直接在原始矩阵上构造平均解与距离,而本项目明确采用“先预处理、再标准化、后计算 EDAS”的路径。因此,若论文结果来自本软件,方法部分应以第 3 节和第 5 节的公式为准,而不能直接套用其他资料中的原始型 EDAS 公式。
7.2 常数列在界面层会被拦截,但核心仍保留兜底
validate_excel_data() 默认不允许常数列进入正式流程;但若直接调用核心类并传入常数列,min-max 情形下常数列会被记为 1,z-score 再映射情形下常数列会被记为 0。这个差异属于项目实现细节,论文复现时最好说明数据是通过界面流程输入,还是直接调用核心代码输入。
7.3 适度指标标准值允许为 0
当前 ui/indicators_widget.py 已允许适度指标标准值取 0。冒烟测试 test_edas_smoke.py 也专门覆盖了该情形。因此,若某一指标的最优目标值本身就是 0,可以直接按当前软件流程建模。
7.4 自定义权重是“全局录入、局部重归一”
用户在权重编辑页录入的是当前全部已选指标的权重;但一旦在结果页进行部分指标分层计算,程序会先截取子集对应的权重,再重新归一化。因此,分层结果中的权重与整体分析中的权重不一定数值相同,但它们遵循同一比例来源。
8. 论文写作模板
若本文采用本项目中的 EDAS 模块对评价对象进行综合评价,可按如下方式描述:
首先构建评价对象与指标组成的原始决策矩阵,并依据指标属性将指标划分为正向指标、负向指标和适度指标。对于适度指标,先根据其与目标值的偏离程度将其转换为效益型指标;随后采用 Max-Min 标准化或 Z-score 标准化将各指标统一映射到无量纲区间。进一步基于标准化矩阵计算各指标的平均解,并分别求得各方案相对于平均解的正距离和负距离。结合熵权法或专家给定权重,计算各方案的加权正距离、加权负距离及 EDAS 综合得分,最终依据综合得分大小完成方案排序。
若本文进一步采用项目中的分层功能,还可补充说明:
在整体评价结果基础上,本文进一步选取部分核心指标重新计算 EDAS 得分,并将局部结果与全指标结果进行对比,以检验指标删减对排序稳定性的影响。
9. 与代码实现的对应关系
表 1 EDAS 关键公式与项目实现对应关系
| 内容 | 数学表达 | 项目实现 |
|---|---|---|
| 原始输入结构 | 式(1)—式(3) | ui/upload_widget.py、utils/data_validator.py、core/edas_calculator.py::set_data |
| 适度指标转换 | 式(4)—式(5) | core/edas_calculator.py::_process_moderate_indicators |
| 标准化方法 | 式(6)—式(13) | core/edas_calculator.py::_normalize_data、ui/methods_widget.py |
| 熵权法 | 式(14)—式(17) | core/edas_calculator.py::_calculate_entropy_weights |
| 自定义权重归一化 | 式(18) | ui/weight_editor_widget.py、core/edas_calculator.py::set_weights |
| 平均解与稳定分母 | 式(19)—式(20) | core/edas_calculator.py::calculate_edas |
| PDA 与 NDA | 式(21)—式(24) | core/edas_calculator.py::calculate_edas |
| \(SP_i\)、\(SN_i\)、\(AS_i\) 与排序 | 式(25)—式(30) | core/edas_calculator.py::calculate_edas |
| Excel、图表、复现脚本与分层结果 | 第 6 节 | core/edas_calculator.py::save_results、append_layer_results、ui/results_widget.py |
总体来看,本项目中的 EDAS 属于“保留平均解距离排序主线,同时扩展适度指标处理、标准化方式、权重来源、复现导出与分层分析”的工程化实现。对论文写作而言,建议把式(19)—式(30)作为 EDAS 主体,再结合式(4)—式(18)说明本软件在预处理、标准化与赋权环节的具体口径。
10. 论文模板补充
10.1 方法描述模板
“本文采用 EDAS 方法对候选方案进行综合评价。首先对原始决策矩阵执行指标类型处理与标准化,并结合熵权法或自定义方式确定指标权重;随后以各指标平均解为参照,分别计算方案相对于平均解的正距离和负距离,并据此构造 EDAS 综合得分,最终完成排序。”
10.2 结果解释模板
结果部分可写为:结果表明,正距离越大且负距离越小的方案,其综合得分通常越高。若分层分析下方案排序与全指标排序保持一致,则说明评价结果具有较好的稳定性;若差异明显,则说明特定指标子集对排序具有显著影响。
10.3 表格标题模板
- 表 1 EDAS 指标类型、标准化方式与权重设置表
- 表 2 EDAS 平均解、正距离与负距离结果表
- 表 3 EDAS 综合得分与排序结果表
- 表 4 EDAS 分层评价结果表
10.4 图表题注模板
- 图 1 EDAS 指标权重分布图。
- 图 2 EDAS 综合得分排序图。
- 图 3 EDAS 分层评价对比图。
10.5 表格示例
表 1 EDAS 综合评价结果表示例
| 方案 | 正距离 \(PDA\) | 负距离 \(NDA\) | 综合得分 \(AS\) | 排名 |
|---|---|---|---|---|
| \(A_1\) | ||||
| \(A_2\) |
表注:综合得分 \(AS\) 越大表示方案越优,排序由综合得分降序确定。
11. 单篇终审补充
11.1 图题与表题对齐建议
参数表可写为:表X EDAS 参数设置表。原始数据表可写为:表X EDAS 原始数据表。标准化矩阵表可写为:表X EDAS 标准化矩阵表。指标权重表可写为:表X EDAS 指标权重表。Step 1_ 平均解AV表可写为:表X EDAS 平均解 AV 结果表。Step 2_ PDA表可写为:表X EDAS 正距离 PDA 结果表。Step 3_ NDA表可写为:表X EDAS 负距离 NDA 结果表。Step 4_ SP_SN表可写为:表X EDAS 加权距离汇总表。Step 5_ NSP_NSN表可写为:表X EDAS 归一化距离汇总表。Step 6_ EDAS得分与排名表可写为:表X EDAS 综合得分与排名表。图表清单表可写为:表X EDAS 图表索引与路径表。weights.png建议写为:图X EDAS 指标权重图。scores.png建议写为:图X EDAS 综合得分图。
11.2 终审说明
- 当前代表性结果目录可采用
results/__codex_edas_direct_run_20260321。其中主工作簿为EDAS_results_20260321_041106.xlsx。 - 当前真实工作表为
参数/原始数据/标准化矩阵/指标权重/Step 1_ 平均解AV/Step 2_ PDA/Step 3_ NDA/Step 4_ SP_SN/Step 5_ NSP_NSN/Step 6_ EDAS得分与排名/图表清单。论文表题应按这套中英混合 sheet 名落地,尤其保留 Step 编号。 - 当前稳定实体图文件为
charts/weights.png与charts/scores.png。如果正文需要解释得分构成,应同时引用Step 2到Step 5的过程表,而不是只展示最终scores.png。 - 真实 repro 脚本为
repro_edas_20260321_041106.py,并通过SRC_FILE = SCRIPT_DIR / 'input_snapshot.xlsx'读取结果包内的输入快照,随后输出到repro_outputs/。它不是统一的repro_inputs/...结构,而是“脚本同目录输入快照 + repro_outputs”口径。 - 当前结果目录会保留多层
repro_outputs/递归复现结果。正文引用时应固定到首层主结果,不要把二次、三次复现结果混入主实验描述。
11.3 全量强化补充
- 本轮按真实磁盘再次核对,算法目录为
具体的算法3/多指标评价/EDAS-基于平均解距离评价法,代表性结果目录为具体的算法3/多指标评价/EDAS-基于平均解距离评价法/results/__codex_edas_direct_run_20260321。 - 该目录主工作簿为
EDAS_results_20260321_041106.xlsx,真实工作表为参数、原始数据、标准化矩阵、指标权重、Step 1_ 平均解AV、Step 2_ PDA、Step 3_ NDA、Step 4_ SP_SN、Step 5_ NSP_NSN、Step 6_ EDAS得分与排名、图表清单。同目录下还保留input_snapshot.xlsx,其作用是作为复现脚本的输入快照,而不是主结果工作簿。 - 当前主图目录为
charts/,实体图为weights.png与scores.png。这两张图与指标权重、Step 6_ EDAS得分与排名的解释最直接对应。 - 当前 repro 口径不是
repro_inputs/...,而是脚本同目录快照:repro_edas_20260321_041106.py中明确写有SRC_FILE = SCRIPT_DIR / 'input_snapshot.xlsx'。同时,该目录还保留了repro_module/、repro_outputs/,说明结果包中连同最小复现模块一起被打包。 repro_outputs/下已经实际生成EDAS_results_20260321_041107.xlsx及下一层repro_outputs/repro_outputs/EDAS_results_20260329_132350.xlsx。因此这篇必须明确写成“主目录 + 多层递归 repro_outputs”的结构,正文不要把递归生成的后续结果混入主实验。- 这篇最适合论文使用的证据仍是首层主结果工作簿、首层
charts/图和首层 repro 脚本;更深层目录只应作为“复现链可继续递归执行”的技术说明。
12. 软件实现核查补充(2026-07)
- 当前实现的主结果目录应写作
具体的算法3/多指标评价/EDAS-基于平均解距离评价法/results/__codex_edas_direct_run_20260321,主工作簿以EDAS_results_20260321_041106.xlsx为准。 - 正文应围绕
参数、原始数据、标准化矩阵、指标权重、Step 1_ 平均解AV、Step 2_ PDA、Step 3_ NDA、Step 4_ SP_SN、Step 5_ NSP_NSN、Step 6_ EDAS得分与排名、图表清单来写。 - 图证应对应
charts/weights.png与charts/scores.png。 repro_edas_20260321_041106.py + SCRIPT_DIR / 'input_snapshot.xlsx'属于脚本同目录输入快照复现口径,正文与附录应和首层主结果目录分开写。