TOPSIS(Technique for Order Preference by Similarity to Ideal Solution)通过计算各方案与正理想解(最优解)和负理想解(最劣解)的相对接近度进行排序。其核心原理可以用三维空间形象表示:
r i j = x i j ∑ i = 1 m x i j 2 r_{ij} = \frac{x_{ij}}{\sqrt{\sum_{i=1}^{m}x_{ij}^2}} rij=∑i=1mxij2xij
方案 | 利润(万元) | 成本(万元) | 交货期(天) |
---|---|---|---|
A | 800 | 300 | 20 |
B | 600 | 250 | 15 |
C | 1000 | 400 | 25 |
归一化结果:
[0.44, 0.53, 0.48]
[0.33, 0.44, 0.36]
[0.55, 0.71, 0.60]
假设权重为[0.5, 0.3, 0.2]:
[0.22, 0.16, 0.10]
[0.17, 0.13, 0.07]
[0.28, 0.21, 0.12]
Z + = ( max z i 1 , min z i 2 , max z i 3 , . . . ) Z^+ = (\max z_{i1}, \min z_{i2}, \max z_{i3}, ...) Z+=(maxzi1,minzi2,maxzi3,...)
Z − = ( min z i 1 , max z i 2 , min z i 3 , . . . ) Z^- = (\min z_{i1}, \max z_{i2}, \min z_{i3}, ...) Z−=(minzi1,maxzi2,minzi3,...)
X = [ 800 300 20 600 250 15 1000 400 25 ] X = \begin{bmatrix} 800 & 300 & 20 \\ 600 & 250 & 15 \\ 1000 & 400 & 25 \\ \end{bmatrix} X= 8006001000300250400201525
import numpy as np
X = np.array([[800,300,20],
[600,250,15],
[1000,400,25]])
# 计算列平方和
sum_squares = np.sum(X**2, axis=0)
# 归一化
normalized = X / np.sqrt(sum_squares)
weights = np.array([0.5, 0.3, 0.2])
weighted = normalized * weights
# 效益型指标取max,成本型取min
positive_ideal = np.array([weighted[:,0].max(),
weighted[:,1].min(),
weighted[:,2].min()])
negative_ideal = np.array([weighted[:,0].min(),
weighted[:,1].max(),
weighted[:,2].max()])
def euclidean_distance(x, y):
return np.sqrt(np.sum((x - y)**2))
d_plus = [euclidean_distance(row, positive_ideal) for row in weighted]
d_minus = [euclidean_distance(row, negative_ideal) for row in weighted]
C = d_minus / (d_plus + d_minus)
指标类型 | 指标项 | 权重 |
---|---|---|
效益型 | 最大航程(km) | 0.3 |
效益型 | 载弹量(kg) | 0.25 |
成本型 | 单价(亿美元) | 0.2 |
区间型 | 巡航速度(Ma) | 0.15 |
效益型 | 雷达探测距离(km) | 0.1 |
机型 | 航程 | 载弹量 | 单价 | 速度 | 雷达 |
---|---|---|---|---|---|
F-35 | 2200 | 6800 | 1.2 | 1.6 | 160 |
歼-20 | 2500 | 7500 | 1.5 | 2.0 | 200 |
苏-57 | 2400 | 8000 | 1.3 | 2.2 | 180 |
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
# 读取数据
data = pd.read_csv('medical_devices.csv')
# 处理特殊指标
data['维护评分'] = data['维护便利性'].map({'优':5, '良':4, '中':3, '差':2})
# 指标方向统一化
data['故障率'] = 1 / data['故障率']
# 归一化处理
scaler = MinMaxScaler()
normalized = scaler.fit_transform(data)
def entropy_weight(data):
# 计算信息熵
p = data / data.sum(axis=0)
entropy = -np.sum(p * np.log(p), axis=0)
# 计算权重
diversity = 1 - entropy
return diversity / diversity.sum()
# 结合主客观权重
final_weights = 0.6*entropy_weights + 0.4*ahp_weights
import matplotlib.pyplot as plt
weight_ranges = np.linspace(0.1, 0.9, 9)
results = []
for w in weight_ranges:
adjusted_weights = [w, 0.3, 0.7-w]
# 重新计算TOPSIS
results.append(calculate_topsis(adjusted_weights))
plt.plot(weight_ranges, results)
plt.xlabel('成本权重变化')
plt.ylabel('最优方案变化')
plt.show()
def mixed_normalization(data, indicators):
"""
data: 原始数据矩阵
indicators: 指标类型列表('benefit','cost','interval')
"""
normalized = np.zeros_like(data)
for i, col in enumerate(data.T):
if indicators[i] == 'benefit':
normalized[:,i] = col / col.max()
elif indicators[i] == 'cost':
normalized[:,i] = col.min() / col
elif indicators[i] == 'interval':
low, high = 50, 80 # 示例区间值
normalized[:,i] = np.where(col < low, 1 - (low - col)/low,
np.where(col > high, 1 - (col - high)/high, 1))
return normalized
import plotly.express as px
fig = px.scatter_3d(df, x='成本', y='效率', z='质量',
color='接近度', size='综合得分',
hover_data=['方案名称'])
fig.update_layout(scene=dict(
xaxis_title='成本(万元)',
yaxis_title='效率(件/小时)',
zaxis_title='质量合格率(%)'))
fig.show()
对比项 | TOPSIS | 简单加权法 | 雷达图法 |
---|---|---|---|
处理维度 | 多维空间 | 线性组合 | 二维投影 |
结果区分度 | 高 | 中等 | 低 |
计算复杂度 | 中等 | 低 | 高 |
可视化难度 | 中等 | 容易 | 困难 |
错误案例:将全部指标视为效益型
错误案例:直接使用原始数据计算
错误案例:忽略权重敏感性分析
Python库:
TOPSIS-Python
:专用实现库scikit-criteria
:多准则决策工具包在线工具:
商业软件:
最新研究趋势:将TOPSIS与机器学习结合,例如: