Topsis(数模加油站自学笔记)

模型原理

TOPSIS法是一种理想目标相似性的顺序选优技术,在多目标决策分析中是一种非常有效的方法。它通过归一化后(去量纲化)的数据规范化矩阵,找出多个目标中最优目标和最劣目标(分别用理归想一解化和反理想解表示),分别计算各评价目标与理想解和反理想解的距离,获得各目标与理想解的贴近度,按理想解贴近度的大小排序,以此作为评价目标优劣的依据。贴近度取值在0~1之间,该值愈接近1,表示相应的评价目标越接近最优水平:反之,该值愈接近0,表示评价目标越接近最劣水平。

基本步骤:

  1. 将原始矩阵正向化,所有的指标类型统一转化为极大型指标。
  2. 正向矩阵标准化,去除量纲的影响,保证不同评价指标在同一数量级,且数据大小排序不变。在这里插入图片描述
    标准化后,还需要给不同指标加上权重,采用的权重确定方法有层次分析法(上一篇笔记)、熵权法、Delphi法、对数最小二乘法等,在这里认为各个指标权重相同。
  3. 计算得分并归一化在这里插入图片描述

例题:

在这里插入图片描述

指标分类:在这里插入图片描述

统一指标类型公式:

在这里插入图片描述在这里插入图片描述
根据上图数据统一指标类型eg:
在这里插入图片描述

计算得分并归一化:

在这里插入图片描述
eg:
在这里插入图片描述

整个过程图:

在这里插入图片描述

代码示例:

import numpy as np

print("输入参评数目:")
n = int(input())
print("输入指标数目:")
m = int(input())

print("请输入类型矩阵:1:极大型 2:极小型 3:中间型 4区间型")
kind = input().split(" ")  # 将输入的字符串按空格分割,形成列表

print("请输入矩阵:")
A = np.zeros(shape=(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


# 极小型指标转化为极大型指标的函数
def minTomax(maxx, x):
    x = list(x)
    ans = [[maxx - e] for e in x]
    return np.array(ans)


# 中间型指标转化为极大型指标的函数
def midTomax(bestx, x):
    x = list(x)
    h = [abs(e - bestx) for e in x]
    M = max(h)
    if M == 0:
        M = 1
    ans = [[[(1 - e / M)] for e in h]]
    return np.array(ans)


# 区间型指标转化为极大型指标的函数
def regTomax(lowx, highx, x):
    x = list(x)
    M = max(lowx - min(x), max(x) - highx)
    if M == 0:
        M = 1
    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])  # append在列表末尾添加元素
    return np.array(ans)


# 统一指标类型,全部转化成极大型指标
X = np.zeros(shape=(n, 1))
for i in range(m):
    if kind[i] == "1":
        v = np.array(A[:, i])
    elif kind[i] == "2":
        maxA = max(A[:, i])
        v = minTomax(maxA,A[:, i])
    elif kind[i] == "3":
        print("类型三:请输入最优值:")
        bestA = eval(input())  # eval包含int和float两种格式
        v = midTomax(bestA, A[:,i])
    elif kind[i] == "4":
        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.astype('float')
for j in range(m):
    X[:, j] = X[:, j] / np.sqrt(sum(X[:, j] ** 2))
print("标准化后矩阵为:\n{}".format(X))

# 最大值最小值距离的计算
x_max = np.max(X,axis=0)
x_min = np.min(X,axis=0)#计算标准化后每列的最小值
d_z = np.sqrt(np.sum(np.square((X - np.tile(x_max,(n,1)))),axis = 1)) #计算每个参评对象与最优情况的距离d+
d_f = np.sqrt(np.sum(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)
Score = 100*s/sum(s)# 得分s转化为百分制
for i in range(len(Score)):
    print(f"第{i+1}个标准化后百分制得分为:{Score[i]}")

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值