参考学习b站: 数学建模学习交流
前言
基本知识可看:TOPSIS法
应用
评价下表中20条河流的水质情况
注:含氧量越高越好;PH值越接近7越好;细菌总数越少越好;植物性营养物量介于10‐20之间最佳,超过20或低于10均不好
步骤如下
- 导入矩阵至matalb
- 判断是否需要正向化
- 对正向化后的矩阵进行标准化
- 计算与最大值的距离和最小值的距离,并算出得分
主函数:
clear;clc
%1.导入矩阵
load data_water_quality.mat
%2.判断是否需要正向化
[n,m] = size(X);
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标'])
Judge = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: ']);
if Judge == 1
Position = input('请输入需要正向化处理的指标所在的列,如[2,3,4]: ');
disp('请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型) ')
Type = input('如[2,1,3]: ');
for i = 1 : size(Position,2)
X(:,Position(i)) = Positivization(X(:,Position(i)),Type(i),Position(i));
end
disp('正向化后的矩阵 X = ')
disp(X)
end
%3.对正向化后的矩阵进行标准化
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);
disp('标准化矩阵 Z = ')
disp(Z)
%4.计算与最大值的距离和最小值的距离,并算出得分
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5;
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ],2) .^ 0.5;
S = D_N ./ (D_P+D_N);
disp('最后的得分为:')
stand_S = S / sum(S)
[sorted_S,index] = sort(stand_S ,'descend')
输入注意Position和Type是两个同维度的行向量,不然没有意义
Positivization函数作用是进行正向化,其一共有三个参数:
- 第一个参数是要正向化处理的那一列向量
X(:,Position(i))
(ps.X(:,n)
表示取第n列的全部元素) - 第二个参数是对应的这一列的指标类型(1:极小型, 2:中间型, 3:区间型)
- 第三个参数是告诉函数正在处理的是原始矩阵中的哪一列
输出变量posit_x
表示:正向化后的列向量,它返回正向化之后的指标,我们将其直接赋值给我们原始要处理的那一列向量
Positivization函数代码:
function [posit_x] = Positivization(x,type,i)
if type == 1 %极小型
disp(['第' num2str(i) '列是极小型,正在正向化'] )
posit_x = Min2Max(x);
disp(['第' num2str(i) '列极小型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 2 %中间型
disp(['第' num2str(i) '列是中间型'] )
best = input('请输入最佳的那一个值: ');
posit_x = Mid2Max(x,best);
disp(['第' num2str(i) '列中间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 3 %区间型
disp(['第' num2str(i) '列是区间型'] )
a = input('请输入区间的下界: ');
b = input('请输入区间的上界: ');
posit_x = Inter2Max(x,a,b);
disp(['第' num2str(i) '列区间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
else
disp('没有这种类型的指标,请检查Type向量中是否有除了1、2、3之外的其他值')
end
end
中间用到的3个函数不再赘述:
Min2Max函数来正向化极小型:
function [posit_x] = Min2Max(x)
posit_x = max(x) - x;
%posit_x = 1 ./ x; %如果x全部都大于0,也可以这样正向化
end
Mid2Max函数来正向化中间型:
function [posit_x] = Mid2Max(x,best)
M = max(abs(x-best));
posit_x = 1 - abs(x-best) / M;
end
Inter2Max函数来正向化列区间型:
function [posit_x] = Inter2Max(x,a,b)
r_x = size(x,1); % row of x
M = max([a-min(x),max(x)-b]);
%zeros函数用法: zeros(3) zeros(3,1) ones(3)
posit_x = zeros(r_x,1);
% 初始化posit_x全为0 初始化的目的是节省处理时间
for i = 1: r_x
if x(i) < a
posit_x(i) = 1-(a-x(i))/M;
elseif x(i) > b
posit_x(i) = 1-(x(i)-b)/M;
else
posit_x(i) = 1;
end
end
end
输入输出:
共有20个评价对象, 4个评价指标
这4个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: 1
请输入需要正向化处理的指标所在的列,例如第2、3、6三列需要处理,那么你需要输入[2,3,6]: [2,3,4]
请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型)
例如:第2列是极小型,第3列是区间型,第6列是中间型,就输入[1,3,2]: [2,1,3]
第2列是中间型
请输入最佳的那一个值: 7
第2列中间型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
第3列是极小型,正在正向化
第3列极小型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
第4列是区间型
请输入区间的下界: 10
请输入区间的上界: 20
第4列区间型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
正向化后的矩阵 X =
4.6900 0.7172 3.0000 1.0000
2.0300 0.4069 35.0000 0.6940
9.1100 0.5241 8.0000 0.9058
8.6100 0.9655 8.0000 0.4443
7.1300 0.6552 4.0000 0.6914
2.3900 0.8414 16.0000 0.6007
7.6900 0.8552 16.0000 0.6551
9.3000 0.8690 27.0000 0
5.4500 0.5724 49.0000 1.0000
6.1900 0.8138 37.0000 0.7848
7.9300 0.6345 45.0000 0.6992
4.4000 0.8069 37.0000 0.5419
7.4600 0.1448 31.0000 1.0000
2.0100 0 7.0000 0.4546
2.0400 0.5862 31.0000 1.0000
7.7300 0.4069 2.0000 1.0000
6.3500 0.6000 29.0000 0.1824
8.2900 0.0276 15.0000 1.0000
3.5400 0.8138 0 0.4088
7.4400 0.4897 46.0000 0.2731
标准化矩阵 Z =
0.1622 0.2483 0.0245 0.3065
0.0702 0.1408 0.2863 0.2127
0.3150 0.1814 0.0655 0.2776
0.2977 0.3342 0.0655 0.1361
0.2466 0.2268 0.0327 0.2119
0.0826 0.2912 0.1309 0.1841
0.2659 0.2960 0.1309 0.2008
0.3216 0.3008 0.2209 0
0.1885 0.1981 0.4009 0.3065
0.2141 0.2817 0.3027 0.2405
0.2742 0.2196 0.3682 0.2143
0.1522 0.2793 0.3027 0.1661
0.2580 0.0501 0.2536 0.3065
0.0695 0 0.0573 0.1393
0.0705 0.2029 0.2536 0.3065
0.2673 0.1408 0.0164 0.3065
0.2196 0.2077 0.2373 0.0559
0.2867 0.0095 0.1227 0.3065
0.1224 0.2817 0 0.1253
0.2573 0.1695 0.3763 0.0837
最后的得分为:
stand_S =
0.0451
0.0478
0.0485
0.0488
0.0431
0.0448
0.0539
0.0510
0.0681
0.0684
0.0702
0.0591
0.0527
0.0192
0.0533
0.0434
0.0466
0.0438
0.0358
0.0565
sorted_S =
0.0702
0.0684
0.0681
0.0591
0.0565
0.0539
0.0533
0.0527
0.0510
0.0488
0.0485
0.0478
0.0466
0.0451
0.0448
0.0438
0.0434
0.0431
0.0358
0.0192
index =
11
10
9
12
20
7
15
13
8
4
3
2
17
1
6
18
16
5
19
14
之后用Excel数据可视化:
排个序:
附
我们可以加入权重,毕竟每个指标的权重可能是不同的
要修改的代码入下:
1.让用户判断是否需要增加权重:
disp('请输入是否需要增加权重向量,需要输入1,不需要输入0')
Judge = input('请输入是否需要增加权重: ');
if Judge == 1
disp(['如果你有3个指标,你就需要输入3个权重,例如要输入[0.25,0.25,0.5]']);
weigh = input(['你需要输入' num2str(m) '个权数。' '请以行向量的形式输入这' num2str(m) '个权重: ']);
OK = 0; % 用来判断用户的输入格式是否正确
while OK == 0
if abs(sum(weigh) - 1)<0.000001 && size(weigh,1) == 1 && size(weigh,2) == m % 这里要注意浮点数的运算是不精准的
OK =1;
else
weigh = input('你输入的有误,请重新输入权重行向量: ');
end
end
else
weigh = ones(1,m) ./ m ; %如果不需要加权重就默认权重都相同,即都为1/m
end
2.计算与最大值的距离和最小值的距离,并算出得分:
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ] .* repmat(weigh,n,1) ,2) .^ 0.5; % D+ 与最大值的距离向量
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ] .* repmat(weigh,n,1) ,2) .^ 0.5; % D- 与最小值的距离向量
S = D_N ./ (D_P+D_N); % 未归一化的得分
disp('最后的得分为:')
stand_S = S / sum(S)
[sorted_S,index] = sort(stand_S ,'descend')
输入输出样例:
共有20个评价对象, 4个评价指标
这4个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: 1
请输入需要正向化处理的指标所在的列,例如第2、3、6三列需要处理,那么你需要输入[2,3,6]: [2,3,4]
请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型)
例如:第2列是极小型,第3列是区间型,第6列是中间型,就输入[1,3,2]: [2,1,3]
第2列是中间型
请输入最佳的那一个值: 7
第2列中间型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
第3列是极小型,正在正向化
第3列极小型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
第4列是区间型
请输入区间的下界: 10
请输入区间的上界: 20
第4列区间型正向化处理完成
~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~
正向化后的矩阵 X =
4.6900 0.7172 3.0000 1.0000
2.0300 0.4069 35.0000 0.6940
9.1100 0.5241 8.0000 0.9058
8.6100 0.9655 8.0000 0.4443
7.1300 0.6552 4.0000 0.6914
2.3900 0.8414 16.0000 0.6007
7.6900 0.8552 16.0000 0.6551
9.3000 0.8690 27.0000 0
5.4500 0.5724 49.0000 1.0000
6.1900 0.8138 37.0000 0.7848
7.9300 0.6345 45.0000 0.6992
4.4000 0.8069 37.0000 0.5419
7.4600 0.1448 31.0000 1.0000
2.0100 0 7.0000 0.4546
2.0400 0.5862 31.0000 1.0000
7.7300 0.4069 2.0000 1.0000
6.3500 0.6000 29.0000 0.1824
8.2900 0.0276 15.0000 1.0000
3.5400 0.8138 0 0.4088
7.4400 0.4897 46.0000 0.2731
请输入是否需要增加权重向量,需要输入1,不需要输入0
请输入是否需要增加权重: 1
如果你有3个指标,你就需要输入3个权重,例如它们分别为0.25,0.25,0.5, 则你需要输入[0.25,0.25,0.5]
你需要输入4个权数。请以行向量的形式输入这4个权重: [0.1 0.2 0.3 0.4]
标准化矩阵 Z =
0.1622 0.2483 0.0245 0.3065
0.0702 0.1408 0.2863 0.2127
0.3150 0.1814 0.0655 0.2776
0.2977 0.3342 0.0655 0.1361
0.2466 0.2268 0.0327 0.2119
0.0826 0.2912 0.1309 0.1841
0.2659 0.2960 0.1309 0.2008
0.3216 0.3008 0.2209 0
0.1885 0.1981 0.4009 0.3065
0.2141 0.2817 0.3027 0.2405
0.2742 0.2196 0.3682 0.2143
0.1522 0.2793 0.3027 0.1661
0.2580 0.0501 0.2536 0.3065
0.0695 0 0.0573 0.1393
0.0705 0.2029 0.2536 0.3065
0.2673 0.1408 0.0164 0.3065
0.2196 0.2077 0.2373 0.0559
0.2867 0.0095 0.1227 0.3065
0.1224 0.2817 0 0.1253
0.2573 0.1695 0.3763 0.0837
最后的得分为:
stand_S =
0.0463
0.0540
0.0469
0.0427
0.0408
0.0458
0.0504
0.0430
0.0730
0.0694
0.0696
0.0599
0.0560
0.0230
0.0603
0.0437
0.0424
0.0458
0.0333
0.0536
sorted_S =
0.0730
0.0696
0.0694
0.0603
0.0599
0.0560
0.0540
0.0536
0.0504
0.0469
0.0463
0.0458
0.0458
0.0437
0.0430
0.0427
0.0424
0.0408
0.0333
0.0230
index =
9
11
10
15
12
13
2
20
7
3
1
18
6
16
8
4
17
5
19
14
这个程序比较大,如果想直接结束程序的运行,可以按ctrl+c
键