正在加载中...

展开本页目录
算法教程EDAS-基于平均解距离评价法

EDAS-基于平均解距离评价法

No.083 · 在线教程

EDAS(Evaluation based on Distance from Average Solution,基于平均解距离评价法)是一种典型的多指标综合评价方法。其核心思想是:先为每个指标构造平均解,再分别衡量各方案相对于平均解的正距离与负距离,随后结合指标权重形成综合得分…

EDAS-基于平均解距离评价法

1. 方法概述

EDAS(Evaluation based on Distance from Average Solution,基于平均解距离评价法)是一种典型的多指标综合评价方法。其核心思想是:先为每个指标构造平均解,再分别衡量各方案相对于平均解的正距离与负距离,随后结合指标权重形成综合得分,并据此完成排序。

就本项目的具体实现而言,EDAS 模块并不是“直接套用教科书公式”,而是采用了一条明确的工程化计算链:

  • 指标类型支持正向指标、负向指标与适度指标;
  • 适度指标先转换为“越接近目标值越优”的效益型变量;
  • 再对全部指标执行 min-maxz-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 表包含:

  • 对象名称列;
  • SP
  • SN
  • NSP
  • NSN
  • EDAS得分
  • 排名

这比最终 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:包含 SPSNNSPNSNEDAS得分排名 的结果表;
  • charts:图表信息;
  • parameters:标准化方法、权重方法、指标类型、所选指标、权重、适度指标标准值、源文件路径等参数。

6.2 Excel、图表与复现脚本

结果页完成计算后,会自动创建结果目录:

  • results/EDAS-基于平均解距离评价法分析结果_<时间戳>/

并在该目录下保存:

  • EDAS_results_<时间戳>.xlsx
  • charts/weights.png
  • charts/scores.png
  • input_snapshot.xlsx
  • repro_edas_<时间戳>.py
  • repro_module/

其中 Excel 默认包含以下工作表:

  • 参数
  • 原始数据
  • 标准化矩阵
  • 指标权重
  • Step 1_ 平均解AV
  • Step 2_ PDA
  • Step 3_ NDA
  • Step 4_ SP_SN
  • Step 5_ NSP_NSN
  • Step 6_ EDAS得分与排名
  • 图表清单

需要特别说明的是:

  • 内存中的 final_results 含有 SPSNNSPNSN 等列;
  • 导出到 Excel 时,这些中间量分别拆分到 Step 4_ SP_SNStep 5_ NSP_NSN
  • Step 6_ EDAS得分与排名 只保留对象名称、EDAS得分排名 三列。

此外,结果页 ui/results_widget.py 还提供“导出复现代码”按钮。即使自动导出的复现脚本已存在,用户仍可在结果页再次显式导出一份脚本与输入快照。

6.3 部分指标子集的分层计算

EDAS 结果页支持对部分指标重新计算。其实现方式是:

  1. 先完成一次整体 EDAS 计算;
  2. 在结果页勾选部分指标;
  3. 调用 calculate_partial_edas(selected_indicators) 对子集重新计算;
  4. 若原来使用自定义权重,则对子集权重重新截取并归一化;
  5. 通过 append_layer_results() 另存为 EDAS_layer_results_<时间戳>.xlsx

该分层结果文件默认包含:

  • EDAS分层评价结果
  • 指标权重
  • 平均解AV
  • PDA
  • NDA
  • SP_SN
  • NSP_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.pyutils/data_validator.pycore/edas_calculator.py::set_data
适度指标转换 式(4)—式(5) core/edas_calculator.py::_process_moderate_indicators
标准化方法 式(6)—式(13) core/edas_calculator.py::_normalize_dataui/methods_widget.py
熵权法 式(14)—式(17) core/edas_calculator.py::_calculate_entropy_weights
自定义权重归一化 式(18) ui/weight_editor_widget.pycore/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_resultsappend_layer_resultsui/results_widget.py

总体来看,本项目中的 EDAS 属于“保留平均解距离排序主线,同时扩展适度指标处理、标准化方式、权重来源、复现导出与分层分析”的工程化实现。对论文写作而言,建议把式(19)—式(30)作为 EDAS 主体,再结合式(4)—式(18)说明本软件在预处理、标准化与赋权环节的具体口径。

10. 论文模板补充

10.1 方法描述模板

“本文采用 EDAS 方法对候选方案进行综合评价。首先对原始决策矩阵执行指标类型处理与标准化,并结合熵权法或自定义方式确定指标权重;随后以各指标平均解为参照,分别计算方案相对于平均解的正距离和负距离,并据此构造 EDAS 综合得分,最终完成排序。”

10.2 结果解释模板

结果部分可写为:结果表明,正距离越大且负距离越小的方案,其综合得分通常越高。若分层分析下方案排序与全指标排序保持一致,则说明评价结果具有较好的稳定性;若差异明显,则说明特定指标子集对排序具有显著影响。

10.3 表格标题模板

  1. 表 1 EDAS 指标类型、标准化方式与权重设置表
  2. 表 2 EDAS 平均解、正距离与负距离结果表
  3. 表 3 EDAS 综合得分与排序结果表
  4. 表 4 EDAS 分层评价结果表

10.4 图表题注模板

  1. 图 1 EDAS 指标权重分布图。
  2. 图 2 EDAS 综合得分排序图。
  3. 图 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.pngcharts/scores.png。如果正文需要解释得分构成,应同时引用 Step 2Step 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_ 平均解AVStep 2_ PDAStep 3_ NDAStep 4_ SP_SNStep 5_ NSP_NSNStep 6_ EDAS得分与排名图表清单。同目录下还保留 input_snapshot.xlsx,其作用是作为复现脚本的输入快照,而不是主结果工作簿。
  • 当前主图目录为 charts/,实体图为 weights.pngscores.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_ 平均解AVStep 2_ PDAStep 3_ NDAStep 4_ SP_SNStep 5_ NSP_NSNStep 6_ EDAS得分与排名图表清单 来写。
  • 图证应对应 charts/weights.pngcharts/scores.png
  • repro_edas_20260321_041106.py + SCRIPT_DIR / 'input_snapshot.xlsx' 属于脚本同目录输入快照复现口径,正文与附录应和首层主结果目录分开写。