数学建模-Topsis法

数学建模-Topsis法

Mel0ny Lv5

Topsis法

矩阵正向化

指标类型

1.极大型(利润型) 越大越好

处理方法:直接找最大值即可

2.极小型(成本型) 越小越好

处理方法:

3.中间型(Ph值) 越靠近某个值越好

处理方法:

数据越好,数据越差

4.区间型(温度) 在某个范围内越好

处理方法:

矩阵标准化

尾濑消除不同指标的量纲

求值

$$
D_+ = \sqrt{\sum^m_{j=1}w_j(Z^+j - z{ij})^2} \[8pt]
D_- = \sqrt{\sum^m_{j=1}w_j(Z^-j - z{ij})^2} \qquad
w_j:权重
\[8pt]
S_i = \frac{D_i^-}{Di^+} + D_i^-
$$

Python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import numpy as np  # 导入numpy库,用于进行科学计算

# Topsis法计算得分,在3.ENT_Entropy文件夹中有用熵权法计算权重的程序

# 从用户输入中接收参评数目和指标数目,并将输入的字符串转换为数值
print("请输入参评数目:")
n = eval(input()) # 接收参评数目
print("请输入指标数目:")
m = eval(input()) # 接收指标数目

# 接收用户输入的类型矩阵,该矩阵指示了每个指标的类型(极大型、极小型等)
print("请输入类型矩阵:1:极大型,2:极小型,3:中间型,4:区间型")
kind = input().split(" ") # 将输入的字符串按空格分割,形成列表

# 接收用户输入的矩阵并转换为numpy数组
print("请输入矩阵:")
A = np.zeros((n, m)) # 初始化一个n行m列的全零矩阵A
for i in range(n):
A[i] = input().split() # 接收每行输入的数据
A[i] = list(map(float, A[i])) # 将接收到的字符串列表转换为浮点数列表
print("输入矩阵为:\n{}".format(A)) # 打印输入的矩阵A
# 90 4 35 15
# 85 3 50 21
# 92 4.5 40 19
# 88 3.5 38 17

# 极小型指标转化为极大型指标的函数
def minTomax(maxx, x):
x = list(x) # 将输入的指标数据转换为列表
ans = [[(maxx-e)] for e in x] # 计算最大值与每个指标值的差,并将其放入新列表中
return np.array(ans) # 将列表转换为numpy数组并返回

# 中间型指标转化为极大型指标的函数
def midTomax(bestx, x):
x = list(x) # 将输入的指标数据转换为列表
h = [abs(e-bestx) for e in x] # 计算每个指标值与最优值之间的绝对差
M = max(h) # 找到最大的差值
if M == 0:
M = 1 # 防止最大差值为0的情况
ans = [[(1-e/M)] for e in h] # 计算每个差值占最大差值的比例,并从1中减去,得到新指标值
return np.array(ans) # 返回处理后的numpy数组

# 区间型指标转化为极大型指标的函数
def regTomax(lowx, highx, x):
x = list(x) # 将输入的指标数据转换为列表
M = max(lowx-min(x), max(x)-highx) # 计算指标值超出区间的最大距离
if M == 0:
M = 1 # 防止最大距离为0的情况
ans = []
for i in range(len(x)):
if x[i]<lowx:
ans.append([(1-(lowx-x[i])/M)]) # 如果指标值小于下限,则计算其与下限的距离比例
elif x[i]>highx:
ans.append([(1-(x[i]-highx)/M)]) # 如果指标值大于上限,则计算其与上限的距离比例
else:
ans.append([1]) # 如果指标值在区间内,则直接取为1
return np.array(ans) # 返回处理后的numpy数组

# 统一指标类型,将所有指标转化为极大型指标
X = np.zeros(shape=(n, 1))
for i in range(m):
if kind[i]=="1": # 如果当前指标为极大型,则直接使用原值
v = np.array(A[:, i])
elif kind[i]=="2": # 如果当前指标为极小型,调用minTomax函数转换
maxA = max(A[:, i])
v = minTomax(maxA, A[:, i])
elif kind[i]=="3": # 如果当前指标为中间型,调用midTomax函数转换
print("类型三:请输入最优值:")
bestA = eval(input())
v = midTomax(bestA, A[:, i])
elif kind[i]=="4": # 如果当前指标为区间型,调用regTomax函数转换
print("类型四:请输入区间[a, b]值a:")
lowA = eval(input())
print("类型四:请输入区间[a, b]值b:")
highA = eval(input())
v = regTomax(lowA, highA, A[:, i])

if i==0:
X = v.reshape(-1, 1) # 如果是第一个指标,直接替换X数组
else:
X = np.hstack([X, v.reshape(-1, 1)]) # 如果不是第一个指标,则将新指标列拼接到X数组上
print("统一指标后矩阵为:\n{}".format(X)) # 打印处理后的矩阵X

# 对统一指标后的矩阵X进行标准化处理
X = X.astype('float') # 确保X矩阵的数据类型为浮点数
for j in range(m):
X[:, j] = X[:, j]/np.sqrt(sum(X[:, j]**2)) # 对每一列数据进行归一化处理,即除以该列的欧几里得范数
print("标准化矩阵为:\n{}".format(X)) # 打印标准化后的矩阵X

# 输入每个指标的权重
print("请输入各指标的权重,用空格分隔,总和应为1:")
w = list(map(float, input().split())) # 接收用户输入的权重
print("各指标权重为:{}".format(w)) # 打印权重w

# 最大值最小值距离的计算
x_max = np.max(X, axis=0) # 计算标准化矩阵每列的最大值
x_min = np.min(X, axis=0) # 计算标准化矩阵每列的最小值
w = np.array(w) # 将输入的权重列表转换为 NumPy 数组,方便计算
d_z = np.sqrt(np.sum(w * np.square((X - np.tile(x_max, (n, 1)))), axis=1)) # 计算每个参评对象与最优情况的距离d+
d_f = np.sqrt(np.sum(w * np.square((X - np.tile(x_min, (n, 1)))), axis=1)) # 计算每个参评对象与最劣情况的距离d-
print('每个指标的最大值:', x_max)
print('每个指标的最小值:', x_min)
print('d+向量:', d_z)
print('d-向量:', d_f)

# 计算每个参评对象的得分排名
s = d_f/(d_z+d_f) # 根据d+和d-计算得分s,其中s接近于1则表示较优,接近于0则表示较劣
for i in range(len(s)):
print('第{}个对象的得分为:{}'.format(i+1,s[i])) # 打印每个参评对象的得分
  • 标题: 数学建模-Topsis法
  • 作者: Mel0ny
  • 创建于 : 2025-11-07 00:14:45
  • 更新于 : 2025-11-07 20:56:26
  • 链接: https://mel0nyrame.github.io/2025/11/07/数学建模-Topsis法/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论