Python實(shí)現(xiàn)“層次分析法”及“自調(diào)節(jié)層次分析法”

姓名:張婧;學(xué)號(hào):20021210706;學(xué)院:電子工程學(xué)院

轉(zhuǎn)載于 :https://blog.csdn.net/Lwwwwwwwl/article/details/115838449

【嵌牛導(dǎo)讀】假設(shè)我們遇到如下問題:

①對(duì)于M個(gè)方案,每個(gè)方案有N個(gè)屬性,在已知各個(gè)方案每個(gè)屬性值&&任意兩個(gè)屬性的重要程度的前提下,如何選擇最優(yōu)的方案?

②對(duì)于一個(gè)層級(jí)結(jié)構(gòu),在已知各底層指標(biāo)相互之間的重要程度下,如何確定各底層指標(biāo)對(duì)最高級(jí)指標(biāo)的權(quán)值?

… …

此時(shí),便可用層次分析法將我們的主觀想法——“誰比誰重要”轉(zhuǎn)換為客觀度量——“權(quán)值”

【嵌牛鼻子】層次分析法? 自調(diào)節(jié)層次分析法

【嵌牛提問】你知道怎么用Python實(shí)現(xiàn)“層次分析法”及“自調(diào)節(jié)層次分析法”嗎?

【嵌牛正文】

層次分析法

層次分析法的基本思想是將復(fù)雜問題分為若干層次和若干因素,在同一層次的各要素之間簡(jiǎn)單地進(jìn)行比較判斷和計(jì)算,并評(píng)估每層評(píng)價(jià)指標(biāo)對(duì)上一層評(píng)價(jià)指標(biāo)的重要程度,確定因素權(quán)重,從而為選擇最優(yōu)方案提出依據(jù)。步驟如下:

(1)根據(jù)自己體系中的關(guān)聯(lián)及隸屬關(guān)系構(gòu)建有層次的結(jié)構(gòu)模型,一般分為三層,分別為最高層、中間層和最低層。

(2)構(gòu)造判斷矩陣

假設(shè)該層有n個(gè)評(píng)價(jià)指標(biāo)u1, u2, …, un,設(shè)cij為ui相對(duì)于uj的重要程度,根據(jù)公式列出的1-9標(biāo)度法,判斷兩兩評(píng)價(jià)指標(biāo)之間的重要性。

根據(jù)比較得出判斷矩陣:

C=(cij)n*n其屬性為cij>0, cji=1/cij,cii=1

(3)層次單排序:從下往上,對(duì)于每一層的每個(gè)判斷矩陣,計(jì)算權(quán)向量和一致性檢驗(yàn)。

計(jì)算矩陣C的最大特征根λmax及對(duì)應(yīng)的特征向量(P1,P2,…, Pn)

一致性指標(biāo)定義為: C I = λ max ? ? n n ? 1 CI = \frac{{{\lambda _{\max }} - n}}{{n - 1}} CI=n?1λmax?n

CI(Consistency Ratio)稱為一致性比例。CI=0時(shí),具有完全一致性;CI接近于0,具有滿意的一致性;CI越大,不一致性越嚴(yán)重。

一致性比率定義為: C R = C I R I < 0.1 {\rm{CR}} = \frac{{{\rm{CI}}}}{{{\rm{RI}}}} < 0.1 CR=RICI<0.1

其中RI稱為隨機(jī)性指標(biāo),參照表如下:

只有當(dāng)CR<0.1,則認(rèn)為該判斷矩陣通過了一致性檢驗(yàn),即該矩陣自相矛盾產(chǎn)生的誤差可忽略。將矩陣C最大特征根對(duì)應(yīng)的特征向量元素作歸一化處理,即可得到對(duì)應(yīng)的權(quán)重集(C1,C2,…,Cn)。

(4)層次總排序

從上往下,依次計(jì)算每一層各指標(biāo)對(duì)最上層指標(biāo)的權(quán)值,以及每一層的綜合一致性比率CR。

自調(diào)節(jié)層次分析法——趙中奇

由于層次分析法選用1-9標(biāo)度構(gòu)建判斷矩陣,而大部分時(shí)候我們自己也不能很好度量重要性的程度,故趙中奇提出用-1,0,1三標(biāo)度來構(gòu)建判斷矩陣。同時(shí),自動(dòng)調(diào)整判斷矩陣,消除前后時(shí)刻主觀比較重要性時(shí)的矛盾現(xiàn)象,即讓矩陣變?yōu)橐恢滦跃仃嚕–R=0)。構(gòu)建并調(diào)整判斷矩陣以及算權(quán)值向量的步驟如下:

(1)初始化m=1

a、確定比較矩陣C=(cij)n*n的第m行元素

b、劃分指標(biāo)集合Dm={j|j=m+1,…,n}為

Hm={j|cmj=-1,j∈Dm}、Mm={j|cmj=0,j∈Dm}與Lm={j|cmj=1,j∈Dm}

并構(gòu)造集合為,其中×表示集合的笛卡爾積

c、若DLm、DMm、DHm全為空集,轉(zhuǎn)d,否則令:

d、若m=n-1,轉(zhuǎn)第二步,否則令m=m+1,轉(zhuǎn)回a

(2)求比較矩陣C

(3)求B=(bij)n*n,其中

(4)求A=(aij)n*n的特征向量,作為各評(píng)價(jià)指標(biāo)的相對(duì)權(quán)重值,其中:


實(shí)例分析

由于網(wǎng)上找到的代碼大多只能算三層的體系,而且沒有趙中奇論文中的自調(diào)節(jié)層次分析法代碼。因此,自己寫了一個(gè)可以計(jì)算超過3層的層次分析法和自調(diào)節(jié)層次分析法代碼!

構(gòu)建如下4層體系

層次分析法得到的權(quán)值

判斷矩陣就不列出來了了,可以在代碼里找到,得到第四層對(duì)A的權(quán)值條形圖如下:

自調(diào)節(jié)層次分析法得到的權(quán)值

自調(diào)節(jié)層次分析法對(duì)高階判斷矩陣更有優(yōu)勢(shì),而算低階判斷矩陣時(shí)的結(jié)果和層次分析法差不多。

代碼

代碼包括了層次分析法與自調(diào)節(jié)層次分析法的實(shí)例,運(yùn)行的時(shí)候注釋掉其中一個(gè)就行!


"""

Created on Tue Jan 26 10:12:30 2021

自適應(yīng)層數(shù)的層次分析法求權(quán)值

@author: lw

"""

import numpy as np

import itertools

import matplotlib.pyplot as plt

#自適應(yīng)層數(shù)的層次分析法

class AHP():

? ? '''

? ? 注意:python中l(wèi)ist與array運(yùn)算不一樣,嚴(yán)格按照格式輸入!

? ? 本層次分析法每個(gè)判斷矩陣不得超過9階,各判斷矩陣必須是正互反矩陣

? ? FA_mx:下一層對(duì)上一層的判斷矩陣集(包含多個(gè)三維數(shù)組,默認(rèn)從目標(biāo)層向方案層依次輸入判斷矩陣。同層的判斷矩陣按順序排列,且上層指標(biāo)不共用下層指標(biāo))

? ? string:默認(rèn)為'norm'(經(jīng)典的層次分析法,需輸入9標(biāo)度判斷矩陣),若為'auto'(自調(diào)節(jié)層次分析法,需輸入3標(biāo)度判斷矩陣)

? ? '''


? ? #初始化函數(shù)

? ? def __init__(self,FA_mx,string='norm'):

? ? ? ? self.RI=np.array([0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49])? #平均隨機(jī)一致性指標(biāo)

? ? ? ? if string=='norm':

? ? ? ? ? ? self.FA_mx=FA_mx? ? ? ? ? #所有層級(jí)的判斷矩陣

? ? ? ? elif string=='auto':

? ? ? ? ? ? self.FA_mx=[]

? ? ? ? ? ? for i in range(len(FA_mx)):

? ? ? ? ? ? ? ? ? temp=[]

? ? ? ? ? ? ? ? ? for j in range(len(FA_mx[i])):

? ? ? ? ? ? ? ? ? ? ? temp.append(self.preprocess(FA_mx[i][j]))

? ? ? ? ? ? ? ? ? self.FA_mx.append(temp)? ? #自調(diào)節(jié)層次分析法預(yù)處理后的所有層級(jí)的判斷矩陣

? ? ? ? self.layer_num=len(FA_mx)? #層級(jí)數(shù)目

? ? ? ? self.w=[]? ? ? ? ? ? ? ? ? #所有層級(jí)的權(quán)值向量

? ? ? ? self.CR=[]? ? ? ? ? ? ? ? #所有層級(jí)的單排序一致性比例

? ? ? ? self.CI=[]? ? ? ? ? ? ? ? #所有層級(jí)下每個(gè)矩陣的一致性指標(biāo)

? ? ? ? self.RI_all=[]? ? ? ? ? ? ? #所有層級(jí)下每個(gè)矩陣的平均隨機(jī)一致性指標(biāo)

? ? ? ? self.CR_all=[]? ? ? ? ? ? #所有層級(jí)的總排序一致性比例

? ? ? ? self.w_all=[]? ? ? ? ? ? ? #所有層級(jí)指標(biāo)對(duì)目標(biāo)的權(quán)值



? ? #輸入單個(gè)矩陣算權(quán)值并一致性檢驗(yàn)(特征根法精確求解)

? ? def count_w(self,mx):

? ? ? ? n=mx.shape[0]

? ? ? ? eig_value, eigen_vectors=np.linalg.eig(mx)

? ? ? ? maxeig=np.max(eig_value)? ? ? ? #最大特征值

? ? ? ? maxindex=np.argmax(eig_value)? ? #最大特征值對(duì)應(yīng)的特征向量

? ? ? ? eig_w=eigen_vectors[:,maxindex]/sum(eigen_vectors[:,maxindex])? ? ? ? #權(quán)值向量

? ? ? ? CI=(maxeig-n)/(n-1)

? ? ? ? RI=self.RI[n-1]

? ? ? ? if(n<=2 and CI==0):

? ? ? ? ? ? ? ? CR=0.0

? ? ? ? else:

? ? ? ? ? ? CR=CI/RI

? ? ? ? if(CR<0.1):

? ? ? ? ? ? return CI,RI,CR,list(eig_w.T)

? ? ? ? else:

? ? ? ? ? ? print('該%d階矩陣一致性檢驗(yàn)不通過,CR為%.3f'%(n,CR))

? ? ? ? ? ? return -1.0,-1.0,-1.0,-1.0


? ? #計(jì)算單層的所有權(quán)值與CR

? ? def onelayer_up(self,onelayer_mx,index):

? ? ? ? num=len(onelayer_mx)? ? ? ? ? #該層矩陣個(gè)數(shù)

? ? ? ? CI_temp=[]

? ? ? ? RI_temp=[]

? ? ? ? CR_temp=[]

? ? ? ? w_temp=[]

? ? ? ? for i in range(num):

? ? ? ? ? ? CI,RI,CR,eig_w=self.count_w(onelayer_mx[i])

? ? ? ? ? ? if(CR>0.1):

? ? ? ? ? ? ? ? print('第%d層的第%d個(gè)矩陣未通過一致性檢驗(yàn)'%(index,i+1))

? ? ? ? ? ? ? ? return

? ? ? ? ? ? CI_temp.append(CI)

? ? ? ? ? ? RI_temp.append(RI)

? ? ? ? ? ? CR_temp.append(CR)

? ? ? ? ? ? w_temp.append(eig_w)

? ? ? ? self.CI.append(CI_temp)

? ? ? ? self.RI_all.append(RI_temp)

? ? ? ? self.CR.append(CR_temp)

? ? ? ? self.w.append(w_temp)


? ? #計(jì)算單層的總排序及該層總的一致性比例

? ? def alllayer_down(self):

? ? ? ? self.CR_all.append(self.CR[self.layer_num-1])

? ? ? ? self.w_all.append(self.w[self.layer_num-1])

? ? ? ? for i in range(self.layer_num-2,-1,-1):

? ? ? ? ? ? if(i==self.layer_num-2):

? ? ? ? ? ? ? ? temp=sum(self.w[self.layer_num-1],[])? ? ? ? #列表降維,扁平化處理,取上一層的權(quán)值向量

? ? ? ? ? ? CR_temp=[]

? ? ? ? ? ? w_temp=[]

? ? ? ? ? ? CR=sum(np.array(self.CI[i])*np.array(temp))/sum(np.array(self.RI_all[i])*np.array(temp))

? ? ? ? ? ? if(CR>0.1):

? ? ? ? ? ? ? ? print('第%d層的總排序未通過一致性檢驗(yàn)'%(self.layer_num-i))

? ? ? ? ? ? ? ? return

? ? ? ? ? ? for j in range(len(self.w[i])):

? ? ? ? ? ? ? ? shu=temp[j]

? ? ? ? ? ? ? ? w_temp.append(list(shu*np.array(self.w[i][j])))

? ? ? ? ? ? temp=sum(w_temp,[])? ? ? ? #列表降維,扁平化處理,取上一層的總排序權(quán)值向量

? ? ? ? ? ? CR_temp.append(CR)

? ? ? ? ? ? self.CR_all.append(CR_temp)

? ? ? ? ? ? self.w_all.append(w_temp)

? ? ? ? return




? ? #計(jì)算所有層的權(quán)值與CR,層次總排序

? ? def run(self):

? ? ? ? for i in range(self.layer_num,0,-1):

? ? ? ? ? ? self.onelayer_up(self.FA_mx[i-1],i)

? ? ? ? self.alllayer_down()

? ? ? ? return



? ? #自調(diào)節(jié)層次分析法的矩陣預(yù)處理過程

? ? def preprocess(self,mx):

? ? ? ? temp=np.array(mx)

? ? ? ? n=temp.shape[0]

? ? ? ? for i in range(n-1):

? ? ? ? ? ? H=[j for j,x in enumerate(temp[i]) if j>i and x==-1]

? ? ? ? ? ? M=[j for j,x in enumerate(temp[i]) if j>i and x==0]

? ? ? ? ? ? L=[j for j,x in enumerate(temp[i]) if j>i and x==1]

? ? ? ? ? ? DL=sum([[i for i in itertools.product(H,M)],[i for i in itertools.product(H,L)],[i for i in itertools.product(M,L)]],[])

? ? ? ? ? ? DM=[i for i in itertools.product(M,M)]

? ? ? ? ? ? DH=sum([[i for i in itertools.product(L,H)],[i for i in itertools.product(M,H)],[i for i in itertools.product(L,M)]],[])

? ? ? ? ? ? if DL:

? ? ? ? ? ? ? ? for j in DL:

? ? ? ? ? ? ? ? ? if(j[0]<j[1] and i<j[0]):

? ? ? ? ? ? ? ? ? ? ? temp[int(j[0])][int(j[1])]=1

? ? ? ? ? ? if DM:

? ? ? ? ? ? ? ? for j in DM:

? ? ? ? ? ? ? ? ? if(j[0]<j[1] and i<j[0]):

? ? ? ? ? ? ? ? ? ? ? temp[int(j[0])][int(j[1])]=0

? ? ? ? ? ? if DH:

? ? ? ? ? ? ? ? for j in DH:

? ? ? ? ? ? ? ? ? if(j[0]<j[1] and i<j[0]):

? ? ? ? ? ? ? ? ? ? ? temp[int(j[0])][int(j[1])]=-1

? ? ? ? for i in range(n):

? ? ? ? ? ? for j in range(i+1,n):

? ? ? ? ? ? ? ? temp[j][i]=-temp[i][j]

? ? ? ? A=[]

? ? ? ? for i in range(n):

? ? ? ? ? ? atemp=[]

? ? ? ? ? ? for j in range(n):

? ? ? ? ? ? ? ? a0=0

? ? ? ? ? ? ? ? for k in range(n):

? ? ? ? ? ? ? ? ? ? a0+=temp[i][k]+temp[k][j]

? ? ? ? ? ? ? ? atemp.append(np.exp(a0/n))

? ? ? ? ? ? A.append(atemp)

? ? ? ? return np.array(A)?




#%%測(cè)試函數(shù)

if __name__=='__main__' :

? ? '''

? ? # 層次分析法的經(jīng)典9標(biāo)度矩陣

? ? goal=[]? ? ? ? ? ? #第一層的全部判斷矩陣

? ? goal.append(np.array([[1, 3],?

? ? ? ? ? ? ? ? [1/3 ,1]]))

? ? criteria1 = np.array([[1, 3],

? ? ? ? ? ? ? ? ? ? ? ? ? [1/3,1]])

? ? criteria2=np.array([[1, 1,3],

? ? ? ? ? ? ? ? ? ? ? ? [1,1,3],

? ? ? ? ? ? ? ? ? ? ? ? [1/3,1/3,1]])

? ? c_all=[criteria1,criteria2]? #第二層的全部判斷矩陣

? ? sample1 = np.array([[1, 1], [1, 1]])

? ? sample2 = np.array([[1,1,1/3], [1,1,1/3],[3,3,1]])

? ? sample3 = np.array([[1, 1/3], [3, 1]])

? ? sample4 = np.array([[1,3,1], [1 / 3, 1, 1/3], [1,3, 1]])

? ? sample5=np.array([[1,3],[1/3 ,1]])

? ? sample_all=[sample1,sample2,sample3,sample4,sample5]? #第三層的全部判斷矩陣

? ? FA_mx=[goal,c_all,sample_all]

? ? A1=AHP(FA_mx)? ? #經(jīng)典層次分析法

? ? A1.run()

? ? a=A1.CR? ? ? ? ? #層次單排序的一致性比例(從下往上)

? ? b=A1.w? ? ? ? ? ? #層次單排序的權(quán)值(從下往上)

? ? c=A1.CR_all? ? ? #層次總排序的一致性比例(從上往下)

? ? d=A1.w_all? ? ? ? #層次總排序的權(quán)值(從上往下)

? ? e=sum(d[len(d)-1],[])? ? ? #底層指標(biāo)對(duì)目標(biāo)層的權(quán)值

? ? #可視化

? ? plt.rcParams['font.sans-serif'] = ['SimHei']

? ? plt.rcParams['axes.unicode_minus'] = False

? ? name=['D1','D2','D3','D4','D5','D6','D7','D8','D9','D10','D11','D12']

? ? plt.figure()

? ? plt.bar(name,e)

? ? for i,j in enumerate(e):

? ? ? ? plt.text(i,j+0.005,'%.4f'%(np.abs(j)),ha='center',va='top')

? ? plt.title('底層指標(biāo)對(duì)A的權(quán)值')

? ? plt.show()

? ? '''


? ? #自調(diào)節(jié)層次分析法的3標(biāo)度矩陣(求在線體系的權(quán)值)

? ? goal=[]? ? ? ? ? ? #第一層的全部判斷矩陣

? ? goal.append(np.array([[0, 1],?

? ? ? ? ? ? ? ? [-1,0]]))

? ? criteria1 = np.array([[0, 1],

? ? ? ? ? ? ? ? ? ? ? ? ? [-1,0]])

? ? criteria2=np.array([[0, 0,1],

? ? ? ? ? ? ? ? ? ? ? ? [0,0,1],

? ? ? ? ? ? ? ? ? ? ? ? [-1,-1,0]])

? ? c_all=[criteria1,criteria2]? #第二層的全部判斷矩陣

? ? sample1 = np.array([[0, 0], [0, 0]])

? ? sample2 = np.array([[0,0,-1], [0,0,-1],[1,1,0]])

? ? sample3 = np.array([[0, -1], [1, 0]])

? ? sample4 = np.array([[0,1,0], [-1, 0,-1], [0,1,0]])

? ? sample5=np.array([[0,1],[-1 ,0]])

? ? sample_all=[sample1,sample2,sample3,sample4,sample5]? #第三層的全部判斷矩陣

? ? FA_mx=[goal,c_all,sample_all]

? ? A1=AHP(FA_mx,'auto')? ? #經(jīng)典層次分析法

? ? A1.run()

? ? a=A1.CR? ? ? ? ? #層次單排序的一致性比例(從下往上)

? ? b=A1.w? ? ? ? ? ? #層次單排序的權(quán)值(從下往上)

? ? c=A1.CR_all? ? ? #層次總排序的一致性比例(從上往下)

? ? d=A1.w_all? ? ? ? #層次總排序的權(quán)值(從上往下)

? ? e=sum(d[len(d)-1],[])? ? ? #底層指標(biāo)對(duì)目標(biāo)層的權(quán)值

? ? #可視化

? ? plt.rcParams['font.sans-serif'] = ['SimHei']

? ? plt.rcParams['axes.unicode_minus'] = False

? ? name=['D1','D2','D3','D4','D5','D6','D7','D8','D9','D10','D11','D12']

? ? plt.figure()

? ? plt.bar(name,e)

? ? for i,j in enumerate(e):

? ? ? ? plt.text(i,j+0.005,'%.4f'%(np.abs(j)),ha='center',va='top')

? ? plt.title('底層指標(biāo)對(duì)A的權(quán)值')

? ? plt.show()

————————————————

版權(quán)聲明:本文為CSDN博主「易~lw」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/Lwwwwwwwl/article/details/115838449

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容