这是李登峰老师《直觉模糊集决策与对策分析方法》第三章的topsis方法,对于给出的算例进行独立重复实验。
相比实数域上的topsis方法,我们可以通过拆分矩阵,拼接矩阵对齐运算等方式实现直觉模糊下的矩阵运算。贴出来供大家学习参考。
关键环节有注释解释,代码如下
import pandas as pd
import numpy as np
from matplotlib.cbook import flatten
def finpis(df):#寻找正负理想解
df1=df.iloc[:,::2]
df2=df.iloc[:,1::2]
df3=df1.max()
df4=df1.min()
df5=df2.max()
df6=df2.min()#准备工作,用很多个切片操作为之后做准备,其实可以优化,看起来确实不美观
df7=list(flatten(zip(df3,df6))) #这里是百度到的如何奇偶项交错插入数列方法
df8=list(flatten(zip(df4,df5)))
df11 = df7[0::2]
df12 = df7[1::2]
c1 = [1-df11[i] - df12[i] for i in range(len(df11))]
c1= pd.Series(c1)
df7= pd.Series(df7)
df13 = df8[0::2]
df14 = df8[1::2]
c2 = [1-df13[i] - df14[i] for i in range(len(df13))]
c2= pd.Series(c2)#c1,c2就是寻找到的正负理想解,考虑到矩阵运算的时候需要犹豫度运算,因此还要找到犹豫度连接到数列头部
df8= pd.Series(df8)
zheng = pd.concat([c1,df7])
fu= pd.concat([c2,df8])
return zheng,fu#带有犹豫度的正负理想解,但并不是需要的
def normalize_matrix(df):#矩阵也需要犹豫度参与运算,因此把犹豫度拼接到头部,只要位置和正负理想解对齐,线性运算就不会出错
df2=df.iloc[:,1::2]
df1=df.iloc[:,::2]
pai=1-df1.values-df2.values
pai =pd.DataFrame(pai)
f=[pai,df]
f= pd.concat(f,axis=1)
return f
def ranks(df,pis,nis):#排名方法,原封不动可以使用实数域的方法代码
pistemp = df.sub(pis, axis=1)
pistempsum = (pistemp ** 2).sum(axis=1)
nistemp = df.sub(nis, axis=1)
nistempsum = (nistemp ** 2).sum(axis=1)
return np.sqrt(nistempsum)/(np.sqrt(pistempsum)+np.sqrt(nistempsum))
if __name__ == '__main__':#主函数列出需要的矩阵,没有使用excel导入
df = [[0.1875, 0.325, 0.21, 0.55, 0.24, 0.72],
[0.20, 0.3625, 0.238, 0.52, 0.135, 0.825],
[0.1, 0.5875, 0.2625, 0.43, 0.18, 0.755]]
df = pd.DataFrame(df)
pis,nis=finpis(df)#一个方法返回两个结果,方便使用
f= normalize_matrix(df)
print('方案收益值为\n ',ranks(f, pis,nis))
10.25进行代码优化。三个函数分别实现寻找正负理想解,计算犹豫度和计算排名的功能。
def finpn(df):
df=df
pis = df.max()
nis = df.min()
for i in range(1,df.shape[1],2):
temp = pis[i]
pis[i] = nis[i]
nis[i] = temp
return pis, nis
def add_matrix(df):
df=df
df2=df.iloc[:,1::2].T.reset_index(drop=True).T
df1=df.iloc[:,::2].T.reset_index(drop=True).T
df3=1-df1-df2
df4= pd.concat([df,df3],axis=1).T.reset_index(drop=True).T
return df4
def ranks(df,pis,nis):#排名方法
df=df
pis=pis
nis=nis
pis1=1-pis[0::2].reset_index(drop=True)-pis[1::2].reset_index(drop=True)
nis1=1-nis[0::2].reset_index(drop=True)-nis[1::2].reset_index(drop=True)
pis2=pis.tolist()+pis1.tolist()
nis2=nis.tolist()+nis1.tolist()
print(pis2,nis2)
pistemp = df.sub(pis2, axis=1)
pistempsum = (pistemp ** 2).sum(axis=1)
nistemp = df.sub(nis2, axis=1)
nistempsum = (nistemp ** 2).sum(axis=1)
return np.sqrt(nistempsum) / (np.sqrt(pistempsum) + np.sqrt(nistempsum))
if __name__ == '__main__':#主函数列出需要的矩阵,没有使用excel导入
df = [[0.1875, 0.325, 0.21, 0.55, 0.24, 0.72],
[0.20, 0.3625, 0.238, 0.52, 0.135, 0.825],
[0.1, 0.5875, 0.2625, 0.43, 0.18, 0.755]]
df = pd.DataFrame(df)
pis,nis=finpn(df)
df=add_matrix(df)
print(df)
print('方案收益值为\n ',ranks(df, pis,nis))
github仓库在https://github.com/rivendelltom/decision-making-study