TODIM-交互式多准则决策法
TODIM(Tomada de Decisao Interativa Multicriterio,交互式多准则决策法)是一类基于前景理论思想的排序方法。其核心特征在于:不是直接对单个方案给出线性加权和,而是对任意两个方案在各指标上的“优势”与“劣势”分别赋予不同形式的效用函数,…
TODIM-交互式多准则决策法
1. 方法概述
TODIM(Tomada de Decisao Interativa Multicriterio,交互式多准则决策法)是一类基于前景理论思想的排序方法。其核心特征在于:不是直接对单个方案给出线性加权和,而是对任意两个方案在各指标上的“优势”与“劣势”分别赋予不同形式的效用函数,再汇总为总体支配度。
就本项目 具体的算法3/多指标评价/TODIM-交互式多准则决策法 的当前实现而言,完整流程为:
- 读取对象列与指标列数据;
- 对正向指标、负向指标、适度指标做同向化处理;
- 对全部指标做
min-max或z-score + min-max标准化; - 通过标准差赋权或自定义权重得到指标权重;
- 以最大权重指标作为参考权重;
- 计算两两方案间的 TODIM 优势函数与总体支配度;
- 计算每个对象的总支配值并归一化为综合得分;
- 按得分排序并导出 Excel、图表与复现脚本。
设共有 \(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} $$
项目最终结果表中的核心列为:
对象得分排名
其中 得分 越大表示对象越优,排名=1 表示最优对象。
2. 输入结构与项目流程
2.1 输入数据要求
上传页 ui/upload_widget.py 支持 .xlsx、.xls 与 .csv 文件,也支持示例数据。结合 utils/data_validator.py,当前项目对输入数据的要求为:
- 第 1 列为对象名称;
- 第 2 列及以后为指标列;
- 指标列必须全部可转为数值;
- 指标列不允许空值;
- 对象名称不允许重复;
- 常数列不允许存在。
因此,进入核心 Calculator.run_analysis() 的数据结构可写为
$$ \mathcal{D}=\{A_i,\ x_{i1},x_{i2},\ldots,x_{in}\}_{i=1}^{m} \tag{3} $$
与 StandardDeviation 类似,当前核心还要求:
- 至少选择 2 个指标;
- 所选指标名必须都存在于数据表中。
2.2 界面参数流程
主窗口 ui/main_window.py 的标准流程为:
- 上传数据;
- 选择参与计算的指标;
- 设置每个指标的类型;
- 在参数页选择标准化方式、权重方式、标准差口径、风险参数 \(\theta\) 及敏感性分析;
- 结果页自动启动 TODIM 计算并导出结果。
方法页 ui/methods_widget.py 当前提供的关键参数为:
normalization:min-max或z-score;weight_method:std或custom;std_ddof:0或1;theta:风险参数;sensitivity:是否开启敏感性分析;sensitivity_delta:权重扰动比例 \(\Delta\)。
若用户选择自定义权重,方法页会显示“设置自定义权重”按钮,并跳转到独立页面 ui/weight_editor_widget.py。该页面支持:
- 逐页录入权重;
- 当前页归一化;
- 保存前自动校验总和是否约等于 1;
- 必要时自动归一化到 1。
这意味着:与 SWARA 不同,TODIM 的自定义权重路径在当前 UI 主流程中是真正打通的。
3. 指标类型处理与标准化口径
3.1 中间矩阵定义
设方向调整后的中间矩阵记为
$$ U=(u_{ij})_{m\times n} \tag{4} $$
3.2 正向指标
若第 \(j\) 个指标为正向指标,则程序直接保留原值:
$$ u_{ij}=x_{ij} \tag{5} $$
3.3 负向指标
若第 \(j\) 个指标为负向指标,当前项目先做一次线性镜像变换:
$$ u_{ij}=x_j^{\max}+x_j^{\min}-x_{ij} \tag{6} $$
其中
$$ x_j^{\max}=\max_{1\le i\le m}x_{ij}, \quad x_j^{\min}=\min_{1\le i\le m}x_{ij} \tag{7} $$
随后再统一进入标准化流程。
3.4 适度指标
若第 \(j\) 个指标为适度指标,项目先构造“越接近目标值越好”的接近度:
$$ u_{ij}=1-\frac{|x_{ij}-t_j|}{\max\left(|x_j^{\max}-t_j|,\ |x_j^{\min}-t_j|\right)} \tag{8} $$
若分母为 0,则程序直接令
$$ u_{ij}=1 \tag{9} $$
这里 \(t_j\) 为适度指标标准值。当前项目在这点上的工程口径必须单独说明:
- 核心
core/calculator.py对适度指标要求必须提供standard_values[col],否则直接报错; - 指标页
ui/indicators_widget.py当前允许适度指标标准值取 0,并且不再强制非零校验; - 因此,若用户在界面中把某列切为“适度指标”但未手工改值,默认会把 0 传给核心。
也就是说,当前 TODIM 模块允许适度指标标准值为 0,但不会像 StandardDeviation 那样自动回退到均值或中位数。
3.5 Z-score 标准化
当用户选择 normalization="z-score" 时,程序先对 \(U\) 做标准分数变换:
$$ z_{ij}=\frac{u_{ij}-\mu_j}{\sigma_j} \tag{10} $$
其中
$$ \mu_j=\frac{1}{m}\sum_{i=1}^{m}u_{ij} \tag{11} $$
$$ \sigma_j=\sqrt{\frac{1}{m}\sum_{i=1}^{m}(u_{ij}-\mu_j)^2} \tag{12} $$
这里使用的是 std(ddof=0),不受 std_ddof 影响。
若 \(\sigma_j=0\),程序直接令该列
$$ z_{ij}=0 \tag{13} $$
随后再统一映射到 \([0,1]\):
$$ n_{ij}=\frac{z_{ij}-z_j^{\min}}{z_j^{\max}-z_j^{\min}} \tag{14} $$
3.6 Min-Max 标准化
当用户选择 normalization="min-max" 时,程序直接对 \(U\) 做线性归一化:
$$ n_{ij}=\frac{u_{ij}-u_j^{\min}}{u_j^{\max}-u_j^{\min}} \tag{15} $$
若分母为 0,则程序把该列直接置为 0。
3.7 最终标准化矩阵
综合上述处理后,TODIM 后续实际使用的标准化矩阵记为
$$ N=(n_{ij})_{m\times n} \tag{16} $$
TODIM 模块不会像某些文献实现那样分别为不同步骤准备不同尺度矩阵,而是直接在 \(N\) 上完成:
- 标准差赋权;
- TODIM 优势函数计算;
- 敏感性分析。
4. 权重确定
4.1 标准差赋权
当 weight_method="std" 时,程序直接对标准化矩阵 \(N\) 的各列计算标准差。设第 \(j\) 个指标列均值为
$$ \bar{n}_j=\frac{1}{m}\sum_{i=1}^{m}n_{ij} \tag{17} $$
则其标准差定义为
$$ s_j=\sqrt{\frac{1}{m-\text{ddof}}\sum_{i=1}^{m}(n_{ij}-\bar{n}_j)^2} \tag{18} $$
其中
$$ \text{ddof}\in\{0,1\} \tag{19} $$
并由参数页中的 std_ddof 决定。
最终权重为
$$ w_j=\frac{s_j}{\sum_{k=1}^{n}s_k} \tag{20} $$
若所有标准差之和不大于 0,则程序直接报错“标准差为 0,无法计算权重”。
4.2 自定义权重
若 analysis_params 中传入 weights,核心会优先使用该权重输入,而不再依赖 weight_method 分支。设用户输入原始权重向量为
$$ \hat{w}=(\hat{w}_1,\hat{w}_2,\ldots,\hat{w}_n)^\top \tag{21} $$
则程序按指标顺序重排后统一归一化:
$$ w_j=\frac{\hat{w}_j}{\sum_{k=1}^{n}\hat{w}_k} \tag{22} $$
若自定义权重数量与指标数量不一致,或权重和不大于 0,则直接报错。
这一点需要单独指出:在核心实现中,weights_input 的优先级高于 weight_method。不过当前主窗口只有在用户明确选择“自定义权重”后才会构造该参数,因此 UI 主流程与用户感知是一致的。
4.3 参考权重
TODIM 计算中需要指定参考权重。当前实现采用“最大权重指标”为参考准则,即
$$ w_r=\max_{1\le j\le n}w_j \tag{23} $$
这正是 _todim_scores() 中的 w_r = np.max(w)。
5. TODIM 优势函数与综合得分
5.1 成对差值
对任意两个对象 \(A_i\) 与 \(A_k\),在第 \(j\) 个指标上的标准化差值定义为
$$ d_{ijk}=n_{ij}-n_{kj} \tag{24} $$
5.2 单指标优势函数
若 \(d_{ijk}\ge 0\),程序采用收益型优势函数
$$ \phi_j(i,k)=\sqrt{\frac{w_j}{w_r}\,d_{ijk}} \tag{25} $$
若 \(d_{ijk}<0\),则采用损失型函数
$$ \phi_j(i,k)= -\frac{1}{\theta}\sqrt{\frac{w_j}{w_r}\,(-d_{ijk})} \tag{26} $$
其中 \(\theta>0\) 为 TODIM 风险参数。当前实现中:
- \(\theta\) 越大,负向差异的惩罚幅度越弱;
- \(\theta\) 越小,负向差异的惩罚越强。
程序会在参数检查阶段强制要求
$$ \theta>0 \tag{27} $$
5.3 总体支配度
对对象 \(A_i\) 相对于对象 \(A_k\) 的总体支配度,程序定义为
$$ \delta(i,k)=\sum_{j=1}^{n}\phi_j(i,k) \tag{28} $$
把所有对象两两比较后,得到支配矩阵
$$ \Delta=\big(\delta(i,k)\big)_{m\times m} \tag{29} $$
代码中 dominance_matrix 即对应式(29)。
5.4 对象总支配值与最终得分
对每个对象 \(A_i\),程序汇总其对所有其他对象的支配值:
$$ \Delta_i=\sum_{k=1}^{m}\delta(i,k) \tag{30} $$
然后再做一次线性归一化,得到最终 TODIM 得分:
$$ S_i=\frac{\Delta_i-\min_r \Delta_r}{\max_r \Delta_r-\min_r \Delta_r} \tag{31} $$
若所有 \(\Delta_i\) 相同,则程序会把所有得分置为 0。
5.5 排名规则
TODIM 当前采用
rank(ascending=False, method="dense")
生成名次,因此排名函数可写为
$$ R_i=\operatorname{rank}_{\downarrow}^{\text{dense}}(S_i) \tag{32} $$
这意味着:若存在并列得分,后续名次不会跳号。例如两个对象并列第 1,则下一名次为第 2,而不是第 3。
这一点与 StandardDeviation 模块使用的 method="min" 不同。
6. 敏感性分析
当参数页勾选敏感性分析时,程序会对每个指标权重分别构造“上调”和“下调”两个场景。
设原始权重为 \(w\),扰动比例为 \(\lambda\),若对第 \(j\) 个指标做正向扰动,则先令
$$ \tilde{w}_j^{(+)}=w_j(1+\lambda) \tag{33} $$
若做负向扰动,则令
$$ \tilde{w}_j^{(-)}=w_j\max(0,1-\lambda) \tag{34} $$
然后统一归一化得到新权重向量,再重新调用 TODIM 得分函数。
设扰动场景下第 \(i\) 个对象得分为 \(S_i^{(\pm,j)}\),则程序输出两项指标:
$$ \operatorname{MaxChange}_j^{(\pm)}= \max_i\left|S_i^{(\pm,j)}-S_i\right| \tag{35} $$
$$ \operatorname{MeanChange}_j^{(\pm)}= \frac{1}{m}\sum_i\left|S_i^{(\pm,j)}-S_i\right| \tag{36} $$
这些结果会写入:
step_results["sensitivity"]- Excel 的
Sensitivity工作表
但只有开启敏感性分析时才会生成。
7. 输出结构、导出内容与复现
7.1 结果字典结构
Calculator.get_results() 返回的统一结果字典包括:
raw_dataprocessed_datastep_resultsfinal_resultschartsparameters
其中:
raw_data仅保存前 5 行预览;processed_data保存对象列名、指标集合和标准化矩阵;step_results保存权重、支配矩阵、\(\Delta_i\) 向量和敏感性分析;final_results保存最终权重和得分排名。
需要注意两点:
raw_data并没有像 StandardDeviation 那样记录shape/columns;processed_data["normalized"]直接存储to_dict(orient="list")结果,而不是 DataFrame 预览对象。
7.2 Excel 工作表
当前模块导出的工作表包括:
ParametersRawDataNormalizedWeightsDominanceMatrixDeltaScoresSensitivityCharts
其中:
DominanceMatrix对应式(29)的支配矩阵;Delta对应式(30)的对象总支配值;Scores包含对象/得分/排名。
7.3 图表输出
当前模块默认输出两张图:
weights.pngscores.png
图表路径会写入 Charts 工作表和结果字典中的 charts 字段。
7.4 输出路径与复现脚本
若不传入 output_file,核心会在模块 results 目录下自动创建
TODIM-交互式多准则决策法分析结果_时间戳
目录,并生成
TODIM结果_时间戳.xlsx
若传入 output_file,则与 StandardDeviation 不同,TODIM 当前会 直接使用该路径,不会额外再套一层时间戳目录。
结果页 ui/results_widget.py 还支持导出复现脚本:
repro_todim_时间戳.py
该脚本会复用:
- 原始数据路径;
- 指标类型;
- 适度指标标准值;
- 标准化方式;
- 权重方式;
- 自定义权重;
std_ddoftheta- 敏感性分析参数。
因此,TODIM 当前已经形成“结果文件 + 图表 + 复现脚本”的完整复现实验输出链。
8. 与代码实现的对应关系
8.1 TODIM 前仍然要先做标准化和同向化
不少文献在介绍 TODIM 时直接从属性差值和优势函数切入,但本项目在进入 TODIM 优势函数之前,明确先做了:
- 正向/负向/适度指标处理;
min-max或z-score + min-max标准化。
因此,项目中的 TODIM 优势函数并不是直接建立在原始矩阵 \(X\) 上,而是建立在标准化矩阵 \(N\) 上。
8.2 权重不一定来自 TODIM 外部
传统 TODIM 经常把权重视为外部给定量。但在本项目中:
- 可以直接用标准差赋权自动生成;
- 也可以走自定义权重;
- 主窗口默认推荐标准差赋权。
因此,这一模块在工程上已经把“客观赋权 + TODIM 排序”合并成一个完整算法页面。
8.3 std_ddof 只影响标准差赋权,不影响 Z-score
这与 StandardDeviation 模块类似,也是一个容易写错的点:
- Z-score 固定使用
ddof=0; std_ddof只影响标准差赋权中的式(18)。
8.4 排名采用 dense 规则
当前 TODIM 已按问题整改说明改为 dense 排名,不再使用会强制拆开并列名次的唯一次序规则。因此,在论文或系统说明中,应该把并列处理写成“dense 规则”。
9. 项目回归测试口径
当前模块已配套如下测试:
Z冒烟测试/test_todim_smoke.pyZ冒烟测试/test_todim_baseline.pyZ冒烟测试/test_todim_ui_flow.py
并有增强回归报告:
Z冒烟测试/TODIM-交互式多准则决策法_增强回归与UI链路报告_20260310.md
9.1 基线参数口径
基线文件 todim_baseline.csv 使用:
- 指标集合:
指标1, 指标2, 指标3 - 指标类型:
正向, 负向, 适度 - 适度指标标准值:
指标3 = 5 - 标准化方式:
min-max - 权重方式:
std - 标准差口径:
std_ddof = 0 - 风险参数:\(\theta = 1.0\)
- 敏感性分析:关闭
在这一代码口径下,权重向量为
$$ w= \big( 0.3391344200,\ 0.3391344200,\ 0.3217311600 \big)^\top \tag{37} $$
对应对象排序为
$$ C \succ A \succ B \succ D \tag{38} $$
对应最终得分为
$$ \big( 1.0000000000,\ 0.6143689308,\ 0.3856310692,\ 0.0000000000 \big) \tag{39} $$
对应总支配值向量为
$$ \big( 1.6329931619,\ -1.6329931619,\ 7.1391467547,\ -7.1391467547 \big) \tag{40} $$
同时,基线测试还验证:
dominance_matrix为 \(4\times 4\);- 权重和为 1;
- 结果工作簿非空。
9.2 UI 流程验证
当前 UI 冒烟测试 test_todim_ui_flow.py 还验证了以下行为:
- 上传
todim_baseline.csv后能自动切到指标页; - 指标页与参数页点击确认后能自动进入结果页;
- 结果页成功显示“打开结果目录”按钮;
- 计算完成后能够通过“重置并回到主页面”返回首页。
因此,上述公式、参数与数值可以直接作为当前项目 TODIM 模块撰写论文说明、系统说明和复现实验文档时的代码依据。
10. 论文写作模板
10.1 方法描述模板
“本文采用 TODIM 方法对备选对象进行多准则排序。首先根据指标属性对原始数据进行同向化处理与标准化,得到标准化矩阵 \(N\)(式(4)–式(16));随后依据标准差赋权或自定义权重确定指标权重(式(17)–式(23)),并以最大权重指标作为参考准则。进一步地,对任意两个对象在各指标上的差值构造收益型与损失型优势函数(式(24)–式(27)),并汇总形成总体支配矩阵 \(\Delta\)(式(28)–式(29))。最终根据总支配值及其归一化得分 \(S_i\)(式(30)–式(31))完成排序(式(32))。”
10.2 结果解释模板
结果部分可写为:TODIM 结果表中的得分 \(S_i\) 越大表示对象整体优势越强。与简单加权和模型不同,TODIM 强调对象之间的两两比较和心理感知式收益/损失差异,因此能够同时体现‘优势收益’与‘劣势惩罚’。其中,风险参数 \(\theta\) 控制损失项的惩罚幅度:\(\theta\) 越大,负向差异的惩罚越弱;\(\theta\) 越小,负向差异的惩罚越强。若研究还进行了敏感性分析,则可进一步从最大变化量与平均变化量两方面评估结果稳健性。
10.3 表格标题模板
- 表 1 TODIM 指标类型、标准值与参数设置表
- 表 2 TODIM 指标权重结果表
- 表 3 TODIM 总支配值与综合得分结果表
- 表 4 TODIM 支配矩阵结果表
- 表 5 TODIM 敏感性分析结果表
10.4 图表题注模板
- 图 1 TODIM 指标权重图。
- 图 2 TODIM 综合得分图。
10.5 表格示例
表 1 TODIM 综合评价结果
| 对象 | 总支配值 \(\Delta_i\) | 综合得分 \(S_i\) | 排名 |
|---|---|---|---|
| A | |||
| B |
表注:总支配值 \(\Delta_i\) 按式(30)计算,综合得分 \(S_i\) 按式(31)归一化得到,取值越大表示对象越优。
表 2 TODIM 敏感性分析结果
| 指标 | 场景 | 最大得分变化 | 平均得分变化 |
|---|---|---|---|
| 指标1 | \(+\lambda\) | ||
| 指标1 | \(-\lambda\) |
表注:敏感性分析中的权重扰动规则见式(33)–式(36),用于评估得分对权重变化的稳定性。
11. 单篇终审补充
11.1 图题与表题对齐建议
Parameters表可写为:表X TODIM 参数设置表。RawData表可写为:表X TODIM 原始数据表。Normalized表可写为:表X TODIM 标准化矩阵表。Weights表可写为:表X TODIM 指标权重表。DominanceMatrix表可写为:表X TODIM 支配矩阵表。Delta表可写为:表X TODIM 总支配值结果表。Scores表可写为:表X TODIM 综合得分与排序表。Charts表可写为:表X TODIM 图表索引表。weights.png建议写为:图X TODIM 指标权重图。scores.png建议写为:图X TODIM 综合得分图。
11.2 终审说明
- 当前代表性结果目录可采用
results/manual_check_20260321_01。其中主工作簿为TODIM_manual.xlsx,复现输出为repro_outputs/TODIM_repro_output.xlsx。 - 当前真实工作表为
Parameters/RawData/Normalized/Weights/DominanceMatrix/Delta/Scores/Charts。论文表题应按这组英文 sheet 名落地。 - 当前稳定实体图文件为
charts/weights.png与charts/scores.png。正文若解释“优势收益/劣势惩罚”,应同时引用DominanceMatrix与Delta两张表,而不是只展示最终得分图。 - 真实 repro 脚本为
repro_todim_portable_20260321_051830.py。它不是读取repro_inputs/...,而是直接通过SRC_XLSX = THIS_DIR / 'TODIM_manual.xlsx'回读主结果簿,再从Parameters和RawData两张表中恢复计算参数与原始数据。附录应把这一“结果簿自恢复复现”机制写清。 - 当前脚本依赖结果目录中的
repro_module/core/。论文若强调可移植复现,应补充说明结果包中已携带必要核心模块,而不是依赖外部主工程导入。
11.3 全量强化补充
- 当前首层主结果目录应固定为
具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01。首层主工作簿为具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01/TODIM_manual.xlsx。 - 当前主工作簿实际工作表为
Parameters、RawData、Normalized、Weights、DominanceMatrix、Delta、Scores、Charts,与旧文一致。复现输出位于首层repro_outputs/TODIM_repro_output.xlsx,但该复现结果不应与TODIM_manual.xlsx并列写成两份主结果。 - 当前首层图文件只有两张,分别是
具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01/charts/weights.png与scores.png。对应的复现图位于具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01/repro_outputs/charts/。 - 当前 repro 脚本为
具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01/repro_todim_portable_20260321_051830.py,其真实输入机制是SRC_XLSX = THIS_DIR / 'TODIM_manual.xlsx',然后从主结果簿的RawData与Parameters中恢复计算条件,再将结果输出到THIS_DIR / 'repro_outputs'。因此它属于标准的“结果簿自恢复复现”口径,而不是repro_inputs/...输入副本口径。 - 当前目录内还打包了
repro_module/core/与repro_module/utils/。因此这篇文档应明确说明:TODIM 的复现可移植性依赖结果包中附带的repro_module,而不是依赖主工程运行时环境去导入原始模块。
12. 软件实现核查补充(2026-07)
- 当前主结果目录应写作
具体的算法3/多指标评价/TODIM-交互式多准则决策法/results/manual_check_20260321_01。 - 正文应围绕
Parameters、RawData、Normalized、Weights、DominanceMatrix、Delta、Scores、Charts来写。 - 图证应对应
weights.png与scores.png,并把优势收益、劣势惩罚与最终得分的关系写清。 - 复现脚本应按
repro_todim_portable_20260321_051830.py + TODIM_manual.xlsx的口径说明;repro_module/是结果包自带的可移植复现依赖。