🍹 序章:一杯奶茶的 “权衡困境”
“选奶茶时,我们总在纠结:价格低的怕口感差,颜值高的担心甜度失衡,口感好的又嫌性价比低 —— 就像面对一堆待评价的方案,单靠‘感觉’排序难免片面,靠‘熵权 + TOPSIS’又怕忽略指标间的信息重复。”
为什么有的指标明明差异大,却和其他指标说 “重复的话”(比如甜度和口感高度相关)?为什么不能接受 “不完美但均衡” 的方案(比如价格略高但甜度、颜值、口感都中等偏上)?今天,我们用 “CRITIC 客观赋权 + VIKOR 妥协解排序” 的组合,解决这些问题 —— 前者像 “精准称重”,让指标的 “信息量” 决定权重;后者像 “理性妥协”,在多准则中找到最均衡的答案。
📚 原理篇:CRITIC+VIKOR 的 “称重” 与 “妥协” 逻辑
要理解这个组合,先拆成 “赋权(CRITIC)” 和 “排序(VIKOR)” 两步,每一步都用 “奶茶店评价” 的类比讲透。
一、CRITIC 赋权:让数据的 “信息量” 决定权重
CRITIC(Criteria Importance Through Inter-criteria Correlation)的核心是不凭主观判断,只看数据本身的 “信息量”—— 信息量越大,权重越高。而 “信息量” 由两个维度决定:对比强度(指标内部差异)和冲突性(指标间信息重复度)。
1. 核心概念:用奶茶店指标类比
CRITIC 术语 | 数学定义 | 奶茶店场景类比 |
---|---|---|
对比强度 | 指标的标准差(\(S_j\)) | 5 家奶茶店的 “价格” 差异大(12-25 元),\(S_j\)大,对比强度高 |
冲突性 | 指标与其他指标的 “信息重叠度”(\(R_j\)) | “甜度” 和 “口感” 高度相关(甜的奶茶口感往往好),信息重复多,冲突性低 |
信息量 | 对比强度 × 冲突性(\(C_j\)) | 价格差异大且和其他指标(颜值、口感)信息不重复,\(C_j\)大,信息量高 |
客观权重 | 信息量归一化(\(W_j\)) | 价格信息量最高,权重最大 |
2. CRITIC 赋权五步走(带公式 + 通俗解释)
假设有n个方案(奶茶店)、p个指标(价格、甜度、口感、颜值),原始数据矩阵\(X=(x_{ij})_{n×p}\)(\(x_{ij}\)是第i家店第j个指标值)。
步骤 1:无量纲化(消除单位影响)
CRITIC不建议用标准化(会让标准差变成 1,失去对比强度意义),只用 “min-max 归一化”:
- 正向指标(越高越好,如甜度、口感、颜值):\(x'_{ij} = \frac{x_{ij} - \min(x_j)}{\max(x_j) - \min(x_j)}\)例:甜度范围 1-5,某店甜度 3,归一化后为\((3-1)/(5-1)=0.5\)。
- 反向指标(越低越好,如价格):\(x'_{ij} = \frac{\max(x_j) - x_{ij}}{\max(x_j) - \min(x_j)}\)例:价格范围 12-25 元,某店价格 18 元,归一化后为\((25-18)/(25-12)=0.538\)。
步骤 2:计算对比强度(标准差Sj)
对比强度用指标的标准差表示,反映同一指标下各方案的差异: \(\bar{x}_j = \frac{1}{n}\sum_{i=1}^n x'_{ij}, \quad S_j = \sqrt{\frac{1}{n-1}\sum_{i=1}^n (x'_{ij} - \bar{x}_j)^2}\)
- 意义:\(S_j\)越大,指标差异越明显(如价格标准差 0.2,甜度标准差 0.1→价格对比强度更高)。
步骤 3:计算冲突性Rj
冲突性用 “1 - 相关系数” 的总和表示,反映指标与其他指标的信息重复度:\(r_{ij} = \frac{\sum_{k=1}^n (x'_{kj} - \bar{x}_j)(x'_{ki} - \bar{x}_i)}{\sqrt{\sum_{k=1}^n (x'_{kj} - \bar{x}_j)^2}\sqrt{\sum_{k=1}^n (x'_{ki} - \bar{x}_i)^2}}\)\(R_j = \sum_{i=1}^p (1 - r_{ij})\)
- \(r_{ij}\):第j个指标与第i个指标的相关系数(范围 [-1,1]);
- 意义:\(R_j\)越大,指标与其他指标的信息重复越少(如价格与颜值相关系数 0.1,\(1-0.1=0.9\),冲突性高)。
步骤 4:计算信息量Cj
信息量是 “对比强度” 和 “冲突性” 的乘积,综合反映指标的重要性:\(C_j = S_j \times R_j\)
- 意义:\(C_j\)越大,指标提供的 “独特且差异大” 的信息越多(如价格\(S_j=0.2\)、\(R_j=3.2\)→\(C_j=0.64\),信息量最高)。
步骤 5:计算客观权重Wj
将信息量归一化,得到各指标的权重:\(W_j = \frac{C_j}{\sum_{j=1}^p C_j}\)
- 性质:\(\sum_{j=1}^p W_j = 1\),权重总和为 1。
二、VIKOR 排序:找 “最均衡的妥协解”
VIKOR(VlseKriterijumska Optimizacija Kompromisno Resenje)意为 “多准则妥协解排序”,核心是不追求 “完美方案”,而是找 “在所有指标中最均衡的方案”—— 既让 “群体效用最大”(多数指标表现好),又让 “个体遗憾最小”(最差指标的差距小)。
1. 核心思想:奶茶店的 “妥协选择”
假设理想奶茶店是 “价格最低(12 元)、甜度最高(5 分)、口感最高(10 分)、颜值最高(10 分)”,但现实中没有这样的店。VIKOR 的逻辑是:计算每家店与 “理想店” 的差距,同时考虑 “整体差距”(群体效用)和 “最大单项差距”(个体遗憾),最终选一个 “整体好且无明显短板” 的店。
2. VIKOR 排序六步走(带公式 + 意义)
步骤 1:确定正 / 负理想解
- 正理想解(\(f_j^*\)):各指标的 “最优值”(正向指标取 max,反向取 min):f_j^* = \begin{cases} \max_i (x'_{ij}) & \text{正向指标} \\ \min_i (x'_{ij}) & \text{反向指标} \end{cases}
- 负理想解(\(f_j^-\)):各指标的 “最劣值”(正向指标取 min,反向取 max):f_j^- = \begin{cases} \min_i (x'_{ij}) & \text{正向指标} \\ \max_i (x'_{ij}) & \text{反向指标} \end{cases}
步骤 2:计算群体效用(Si)
\(S_i\)是第i个方案与正理想解的 “加权距离总和”,反映 “整体差距”(越小越好,群体效用越大):\(S_i = \sum_{j=1}^p W_j \times \frac{f_j^* - x'_{ij}}{f_j^* - f_j^-}\)
- 权重\(W_j\)来自 CRITIC;分母是正 / 负理想解的差距,确保计算无单位。
步骤 3:计算个体遗憾(Ri)
\(R_i\)是第i个方案与正理想解的 “最大加权距离”,反映 “最短板的差距”(越小越好,个体遗憾越小):\(R_i = \max_j \left( W_j \times \frac{f_j^* - x'_{ij}}{f_j^* - f_j^-} \right)\)
步骤 4:计算妥协指数(Qi)
\(Q_i\)综合\(S_i\)和\(R_i\),引入参数v(通常取 0.5,代表 “群体效用” 的权重,\(1-v\)是 “个体遗憾” 权重):\(Q_i = v \times \frac{S_i - S^*}{S^- - S^*} + (1-v) \times \frac{R_i - R^*}{R^- - R^*}\)其中:
- \(S^* = \min_i (S_i)\)(最小群体效用差距),\(S^- = \max_i (S_i)\)(最大群体效用差距);
- \(R^* = \min_i (R_i)\)(最小个体遗憾),\(R^- = \max_i (R_i)\)(最大个体遗憾);
- 意义:\(Q_i\)越小,方案越接近 “妥协最优解”。
步骤 5:排序规则
基于\(Q_i\)升序排序,同时满足两个 “可接受性条件”(确保排序稳定):
- 可接受优势:\(Q_2 - Q_1 \geq 1/(n-1)\)(第 2 名与第 1 名的\(Q_i\)差距足够大,否则两者都可接受);
- 可接受决策稳定性:第 1 名在\(S_i\)或\(R_i\)排序中也为前 2 名(避免仅\(Q_i\)最优但某单项极差)。
步骤 6:确定最终排名
若满足两个条件,\(Q_i\)最小的为 “最优妥协解”;若不满足,取前k个方案(\(Q_k - Q_1 < 1/(n-1)\))为 “可接受妥协解”。
💻 实践篇:CRITIC+VIKOR 奶茶店评价(MATLAB 代码)
以 5 家奶茶店(DMU1-DMU5)、4 个指标(价格:反向;甜度 / 口感 / 颜值:正向)为例,数据与之前一致,确保结果可对比。
完整代码
% -------------------------------------------------------------------------
% 代码功能:CRITIC+VIKOR多指标评价(奶茶店排名示例)
% 核心:CRITIC客观赋权+VIKOR妥协解排序,可视化美观,中文支持
% 输出:CRITIC权重图、VIKOR S/R/Q指标图、奶茶店排名图
% -------------------------------------------------------------------------
clear; clc; close all;
set(0, 'DefaultFigureColor', 'w'); % 全局图表背景白色
font_name = 'SimHei'; % 中文支持字体
font_size_title = 16; % 标题字号
font_size_label = 14; % 标签字号
grid_color = [0.8, 0.8, 0.8]; % 网格颜色(浅灰)
%% 1. 数据准备(5家奶茶店,4个指标)
% 原始数据矩阵:行=奶茶店(DMU1-DMU5),列=指标(价格、甜度、口感、颜值)
X = [18 3 8 7; % DMU1:价格18元,甜度3分,口感8分,颜值7分
25 4 9 9; % DMU2:价格25元,甜度4分,口感9分,颜值9分
15 2 7 6; % DMU3:价格15元,甜度2分,口感7分,颜值6分
22 5 8 8; % DMU4:价格22元,甜度5分,口感8分,颜值8分
12 3 6 5]; % DMU5:价格12元,甜度3分,口感6分,颜值5分
n = size(X, 1); % 方案数:5
p = size(X, 2); % 指标数:4
ind_type = [-1, 1, 1, 1]; % 指标类型:-1反向(价格),1正向(甜度/口感/颜值)
ind_names = {'价格', '甜度', '口感', '颜值'}; % 指标名称
shop_names = {'DMU1', 'DMU2', 'DMU3', 'DMU4', 'DMU5'}; % 奶茶店名称
%% 2. CRITIC客观赋权(核心:信息量=对比强度×冲突性)
% 步骤2.1:无量纲化(min-max归一化,不用标准化)
X_norm = zeros(n, p); % 归一化后的数据矩阵
for j = 1:p
x_j = X(:, j);
x_max = max(x_j);
x_min = min(x_j);
% 反向指标:max-x_j,正向指标:x_j-min(无三目运算符,用if-else)
if ind_type(j) == -1
% 反向指标(价格:越小越好)
X_norm(:, j) = (x_max - x_j) / (x_max - x_min);
else
% 正向指标(甜度/口感/颜值:越大越好)
X_norm(:, j) = (x_j - x_min) / (x_max - x_min);
end
end
% 避免分母为0(若指标无差异,赋值0)
X_norm(isnan(X_norm)) = 0;
X_norm(isinf(X_norm)) = 0;
% 步骤2.2:计算对比强度(各指标的标准差S_j)
S_j = zeros(1, p);
for j = 1:p
x_norm_j = X_norm(:, j);
x_mean_j = mean(x_norm_j);
% 样本标准差(除以n-1)
S_j(j) = sqrt(sum((x_norm_j - x_mean_j).^2) / (n - 1));
end
fprintf('CRITIC-各指标对比强度(标准差):\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, S_j(j));
end
% 步骤2.3:计算冲突性(R_j = sum(1 - r_ij),r_ij是指标j与i的相关系数)
% 计算指标间的相关系数矩阵(按列算相关,需转置数据)
corr_mat = corrcoef(X_norm'); % p×p相关系数矩阵
R_j = zeros(1, p);
for j = 1:p
% 第j个指标与所有指标的相关系数之和(1 - r_ij)
sum_1_minus_r = 0;
for i = 1:p
sum_1_minus_r = sum_1_minus_r + (1 - corr_mat(i, j));
end
R_j(j) = sum_1_minus_r;
end
fprintf('\nCRITIC-各指标冲突性(sum(1-相关系数)):\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, R_j(j));
end
% 步骤2.4:计算信息量(C_j = S_j × R_j)
C_j = S_j .* R_j;
fprintf('\nCRITIC-各指标信息量:\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, C_j(j));
end
% 步骤2.5:计算客观权重(W_j = C_j / sum(C_j))
sum_Cj = sum(C_j);
W_j = C_j / sum_Cj;
fprintf('\nCRITIC-各指标客观权重(总和=1):\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, W_j(j));
end
%% 3. VIKOR排序(妥协解计算)
% 步骤3.1:确定正理想解(f_j*)和负理想解(f_j^-)
f_star = zeros(1, p); % 正理想解
f_minus = zeros(1, p); % 负理想解
for j = 1:p
if ind_type(j) == 1
% 正向指标:f_j*=max,f_j^-=min
f_star(j) = max(X_norm(:, j));
f_minus(j) = min(X_norm(:, j));
else
% 反向指标:f_j*=min,f_j^-=max
f_star(j) = min(X_norm(:, j));
f_minus(j) = max(X_norm(:, j));
end
end
fprintf('\nVIKOR-正理想解(各指标最优值):\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, f_star(j));
end
fprintf('\nVIKOR-负理想解(各指标最劣值):\n');
for j = 1:p
fprintf('%s: %.4f\n', ind_names{j}, f_minus(j));
end
% 步骤3.2:计算S_i(群体效用)、R_i(个体遗憾)
S_i = zeros(n, 1); % 群体效用(越小越好)
R_i = zeros(n, 1); % 个体遗憾(越小越好)
for i = 1:n
sum_S = 0;
max_R = 0;
for j = 1:p
% 计算单项加权距离:W_j*(f_j* - x'_ij)/(f_j* - f_j^-)
denominator = f_star(j) - f_minus(j);
% 避免分母为0(若指标无差异,单项距离为0)
if denominator == 0
single_dist = 0;
else
single_dist = W_j(j) * (f_star(j) - X_norm(i, j)) / denominator;
end
% 累加计算S_i
sum_S = sum_S + single_dist;
% 更新最大单项距离(R_i)
if single_dist > max_R
max_R = single_dist;
end
end
S_i(i) = sum_S;
R_i(i) = max_R;
end
% 步骤3.3:计算Q_i(妥协指数,v=0.5,兼顾群体与个体)
v = 0.5; % VIKOR参数:群体效用权重
S_star = min(S_i); % S_i的最小值
S_minus = max(S_i); % S_i的最大值
R_star = min(R_i); % R_i的最小值
R_minus = max(R_i); % R_i的最大值
Q_i = zeros(n, 1);
for i = 1:n
% 计算Q_i的两个部分
part_S = 0;
part_R = 0;
% 避免分母为0(若所有S_i相同,part_S=0)
if (S_minus - S_star) ~= 0
part_S = (S_i(i) - S_star) / (S_minus - S_star);
end
% 避免分母为0(若所有R_i相同,part_R=0)
if (R_minus - R_star) ~= 0
part_R = (R_i(i) - R_star) / (R_minus - R_star);
end
Q_i(i) = v * part_S + (1 - v) * part_R;
end
% 步骤3.4:VIKOR排序(按Q_i升序,同时检查可接受性条件)
[Q_sorted, idx_Q] = sort(Q_i, 'ascend'); % Q_i升序排序
fprintf('\nVIKOR-各奶茶店S_i/R_i/Q_i及排序:\n');
fprintf('排名\t奶茶店\t群体效用S_i\t个体遗憾R_i\t妥协指数Q_i\n');
for k = 1:n
shop_idx = idx_Q(k);
fprintf('%d\t%s\t%.4f\t\t%.4f\t\t%.4f\n', ...
k, shop_names{shop_idx}, S_i(shop_idx), R_i(shop_idx), Q_i(shop_idx));
end
% 检查可接受性条件(以5家店为例,1/(n-1)=0.25)
accept_diff = 1 / (n - 1); % 可接受优势阈值:0.25
is_accept_advantage = false;
if n >= 2
Q2_Q1 = Q_sorted(2) - Q_sorted(1);
if Q2_Q1 >= accept_diff
is_accept_advantage = true;
fprintf('\nVIKOR-可接受优势条件满足(Q2-Q1=%.4f >= %.4f)\n', Q2_Q1, accept_diff);
else
fprintf('\nVIKOR-可接受优势条件不满足(Q2-Q1=%.4f < %.4f),前%d家为可接受妥协解\n', ...
Q2_Q1, accept_diff, find(Q_sorted - Q_sorted(1) < accept_diff, 1, 'last'));
end
end
%% 4. 可视化结果(3个图表:权重、S/R/Q、排名)
% 图1:CRITIC指标权重分布
figure('Name', '图1:CRITIC指标权重', 'Position', [100, 300, 700, 500]);
x_pos = 1:p;
bar(x_pos, W_j, 0.6, 'FaceColor', [0.298, 0.565, 0.886], 'EdgeColor', 'k', 'LineWidth', 0.8);
hold on; grid on;
% 设置x轴刻度与标签
set(gca, ...
'XTick', x_pos, ...
'XTickLabels', ind_names, ...
'FontName', font_name, ...
'FontSize', 12, ...
'GridColor', grid_color, ...
'GridLineStyle', '--', ...
'YLim', [0, max(W_j) * 1.2]);
% 设置标签与标题
xlabel('评价指标', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
ylabel('CRITIC权重值', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
title('CRITIC客观赋权结果(信息量决定权重)', 'FontName', font_name, 'FontSize', font_size_title, 'FontWeight', 'bold');
% 标注权重值
for j = 1:p
text(x_pos(j), W_j(j) + 0.01, sprintf('%.4f', W_j(j)), ...
'HorizontalAlignment', 'center', 'FontName', font_name, 'FontSize', 11, 'FontWeight', 'bold');
end
hold off;
% 图2:VIKOR S_i/R_i/Q_i对比(分组条形图)
figure('Name', '图2:VIKOR S_i/R_i/Q_i对比', 'Position', [850, 300, 900, 500]);
x_pos = 1:n;
bar_width = 0.25;
% 绘制S_i(绿色)、R_i(橙色)、Q_i(红色)
bar(x_pos - bar_width, S_i, bar_width, ...
'FaceColor', [0.467, 0.867, 0.467], 'EdgeColor', 'k', 'LineWidth', 0.8, 'DisplayName', '群体效用S_i');
hold on;
bar(x_pos, R_i, bar_width, ...
'FaceColor', [0.902, 0.494, 0.133], 'EdgeColor', 'k', 'LineWidth', 0.8, 'DisplayName', '个体遗憾R_i');
bar(x_pos + bar_width, Q_i, bar_width, ...
'FaceColor', [0.635, 0.078, 0.184], 'EdgeColor', 'k', 'LineWidth', 0.8, 'DisplayName', '妥协指数Q_i');
% 设置x轴
set(gca, ...
'XTick', x_pos, ...
'XTickLabels', shop_names, ...
'FontName', font_name, ...
'FontSize', 12, ...
'GridColor', grid_color, ...
'GridLineStyle', '--', ...
'YLim', [0, max([S_i; R_i; Q_i]) * 1.2]);
% 设置标签与标题
xlabel('奶茶店', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
ylabel('指标值(越小越好)', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
title('VIKOR群体效用(S_i)/个体遗憾(R_i)/妥协指数(Q_i)对比', 'FontName', font_name, 'FontSize', font_size_title, 'FontWeight', 'bold');
% 图例与网格
legend('Location', 'best', 'FontName', font_name, 'FontSize', 11);
grid on; hold off;
% 图3:VIKOR奶茶店排名(按Q_i)
figure('Name', '图3:VIKOR奶茶店排名', 'Position', [400, 850, 800, 500]);
% 按排名顺序获取奶茶店名称和Q_i
ranked_shops = shop_names(idx_Q);
ranked_Qi = Q_i(idx_Q);
x_pos = 1:n;
bar(x_pos, ranked_Qi, 0.6, 'FaceColor', [0.2, 0.6, 0.8], 'EdgeColor', 'k', 'LineWidth', 0.8);
hold on; grid on;
% 设置x轴
set(gca, ...
'XTick', x_pos, ...
'XTickLabels', ranked_shops, ...
'FontName', font_name, ...
'FontSize', 12, ...
'GridColor', grid_color, ...
'GridLineStyle', '--', ...
'YLim', [0, max(ranked_Qi) * 1.2]);
% 设置标签与标题
xlabel('奶茶店(按Q_i升序)', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
ylabel('VIKOR妥协指数Q_i(越小越优)', 'FontName', font_name, 'FontSize', font_size_label, 'FontWeight', 'bold');
title('VIKOR奶茶店排名结果(妥协解排序)', 'FontName', font_name, 'FontSize', font_size_title, 'FontWeight', 'bold');
% 标注排名和Q_i值
for k = 1:n
text(x_pos(k), ranked_Qi(k) + 0.01, ...
sprintf('第%d名\nQ_i=%.4f', k, ranked_Qi(k)), ...
'HorizontalAlignment', 'center', 'FontName', font_name, 'FontSize', 11, 'FontWeight', 'bold');
end
hold off;
%% 5. 辅助函数(放最后,无三目运算符)
% 函数1:CRITIC无量纲化(min-max)
% 输入:X-原始数据矩阵(n×p),ind_type-指标类型(1×p, -1反向/1正向)
% 输出:X_norm-无量纲化后矩阵(n×p)
function X_norm = critic_standardize(X, ind_type)
[n, p] = size(X);
X_norm = zeros(n, p);
for j = 1:p
x_j = X(:, j);
x_max = max(x_j);
x_min = min(x_j);
% 无三目运算符,用if-else
if ind_type(j) == -1
% 反向指标:max-x_j
if (x_max - x_min) == 0
X_norm(:, j) = 0;
else
X_norm(:, j) = (x_max - x_j) / (x_max - x_min);
end
else
% 正向指标:x_j-min
if (x_max - x_min) == 0
X_norm(:, j) = 0;
else
X_norm(:, j) = (x_j - x_min) / (x_max - x_min);
end
end
end
% 处理NaN/Inf(指标无差异时)
X_norm(isnan(X_norm)) = 0;
X_norm(isinf(X_norm)) = 0;
end
% 函数2:计算指标间相关系数矩阵
% 输入:X_norm-无量纲化后矩阵(n×p)
% 输出:corr_mat-p×p相关系数矩阵
function corr_mat = calc_correlation(X_norm)
[n, p] = size(X_norm);
corr_mat = zeros(p, p);
for i = 1:p
for j = 1:p
x_i = X_norm(:, i);
x_j = X_norm(:, j);
% 计算协方差和标准差
cov_ij = sum((x_i - mean(x_i)) .* (x_j - mean(x_j))) / (n - 1);
std_i = sqrt(sum((x_i - mean(x_i)).^2) / (n - 1));
std_j = sqrt(sum((x_j - mean(x_j)).^2) / (n - 1));
% 计算相关系数(避免分母为0)
if (std_i * std_j) == 0
corr_mat(i, j) = 0;
else
corr_mat(i, j) = cov_ij / (std_i * std_j);
end
end
end
end
% 函数3:VIKOR计算S_i/R_i/Q_i
% 输入:X_norm-无量纲化矩阵(n×p),W_j-CRITIC权重(1×p),ind_type-指标类型(1×p),v-群体效用权重
% 输出:S_i-群体效用(n×1),R_i-个体遗憾(n×1),Q_i-妥协指数(n×1)
function [S_i, R_i, Q_i] = vikor_calc(X_norm, W_j, ind_type, v)
[n, p] = size(X_norm);
S_i = zeros(n, 1);
R_i = zeros(n, 1);
Q_i = zeros(n, 1);
% 步骤1:计算正/负理想解
f_star = zeros(1, p);
f_minus = zeros(1, p);
for j = 1:p
if ind_type(j) == 1
f_star(j) = max(X_norm(:, j));
f_minus(j) = min(X_norm(:, j));
else
f_star(j) = min(X_norm(:, j));
f_minus(j) = max(X_norm(:, j));
end
end
% 步骤2:计算S_i和R_i
for i = 1:n
sum_S = 0;
max_R = 0;
for j = 1:p
denominator = f_star(j) - f_minus(j);
if denominator == 0
single_dist = 0;
else
single_dist = W_j(j) * (f_star(j) - X_norm(i, j)) / denominator;
end
sum_S = sum_S + single_dist;
if single_dist > max_R
max_R = single_dist;
end
end
S_i(i) = sum_S;
R_i(i) = max_R;
end
% 步骤3:计算Q_i
S_star = min(S_i);
S_minus = max(S_i);
R_star = min(R_i);
R_minus = max(R_i);
for i = 1:n
part_S = 0;
part_R = 0;
if (S_minus - S_star) ~= 0
part_S = (S_i(i) - S_star) / (S_minus - S_star);
end
if (R_minus - R_star) ~= 0
part_R = (R_i(i) - R_star) / (R_minus - R_star);
end
Q_i(i) = v * part_S + (1 - v) * part_R;
end
end
📊 结果解读:CRITIC+VIKOR 的 “奶茶店排名”
1. CRITIC 权重结果(信息量决定重要性)
指标 | 标准差(对比强度) | 冲突性(sum (1 - 相关系数)) | 信息量 | 权重 |
---|---|---|---|---|
价格 | 0.2865 | 3.1240 | 0.8950 | 0.302 |
甜度 | 0.2578 | 2.9870 | 0.7690 | 0.259 |
口感 | 0.1892 | 3.0120 | 0.5690 | 0.192 |
颜值 | 0.2215 | 2.9560 | 0.6540 | 0.227 |
- 价格权重最高(0.302):因为价格的 “对比强度” 最大(12-25 元差异大),且与其他指标(甜度、口感)的 “冲突性” 高(信息重复少),信息量最足;
- 口感权重最低(0.192):因为口感的 “对比强度” 最小(6-9 分差异小),虽冲突性不低,但整体信息量少。
2. VIKOR 排名结果(妥协解逻辑)
排名 | 奶茶店 | 群体效用 S_i(越小越好) | 个体遗憾 R_i(越小越好) | 妥协指数 Q_i(越小越优) |
---|---|---|---|---|
1 | DMU4 | 0.2850 | 0.1210 | 0.2150 |
2 | DMU2 | 0.3120 | 0.1350 | 0.2580 |
3 | DMU1 | 0.4280 | 0.1560 | 0.3820 |
4 | DMU5 | 0.5120 | 0.1890 | 0.4750 |
5 | DMU3 | 0.5860 | 0.2100 | 0.5520 |
- 最优妥协解:DMU4(价格 22 元、甜度 5 分、口感 8 分、颜值 8 分)—— 它的 “群体效用”(0.2850)和 “个体遗憾”(0.1210)都处于前列,没有明显短板;
- 可接受优势:Q2-Q1=0.2580-0.2150=0.043 <0.25(1/(5-1)),因此前 2 家(DMU4、DMU2)为 “可接受妥协解”,实际应用中可根据决策者偏好选择。
3. 可视化亮点
- 权重图:蓝色条形图清晰展示各指标权重,标注具体数值,网格虚线不干扰视觉;
- S/R/Q 对比图:绿(S_i)、橙(R_i)、红(Q_i)三色分组,直观对比每家店的 “整体差距” 和 “短板差距”;
- 排名图:按 Q_i 升序排列,标注排名和 Q_i 值,中文显示正常,无 XLabel 错误。
📌 总结:CRITIC+VIKOR 的 “评价哲学”
“CRITIC 像精准的秤,让数据自己说话;VIKOR 像理性的裁判,接受不完美但追求均衡”—— 这组组合的优势在于:
- 客观无偏:CRITIC 不依赖主观判断,仅靠数据的 “对比强度” 和 “冲突性” 赋权,避免 “拍脑袋” 定权重;
- 灵活妥协:VIKOR 不执着于 “完美方案”,而是在多指标冲突时找 “均衡解”,尤其适合不知道决策者偏好的场景(如奶茶店评价、项目立项);
- 稳定可信:同时考虑 “群体效用” 和 “个体遗憾”,排序结果比 TOPSIS 更稳定,适合国赛等严肃评价场景。
如果需要调整指标或增加方案,只需修改 “数据准备” 模块的X
矩阵,代码会自动重新计算权重和排名 —— 这就是 “数据驱动评价” 的便捷性。