天天看點

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

Hello大家好,今年數學模組化國賽将于9月中旬舉行,是時候提前做一些準備了。

本次模型非常簡單,隻是介紹比較得詳細,我下次注意,争取限制下字數。

文末準備了 層次分析-python  模型的實作,簡單懂得模型原理便能一眼看懂代碼。

文章目錄

一、層次分析法的例題

1.1 兩兩比較獲得判斷矩陣

1.2 一緻性正互反矩陣的引入

1.2.1 一緻性檢驗的步驟

1.3 根據一緻性正互反矩陣計算權重 

二、層次分析法

步驟:

三、層次分析法的一些局限性

四、模型拓展

1. 多個準則層: 

2. 準則不對應全部方案:

*3. 一個準則隻對應自己的方案

五、代碼展示

代碼1:

代碼2: 

層次分析(The analytic hierarchy process) 簡稱AHP,是模組化比賽中最基礎的模型之一,其主要用于解決評價類問題(例如:選擇哪種方案最好、哪位運動員或者員工表現的更優秀等。) 

該方法仍具有較強的主觀性,判斷/比較矩陣的構造在一定程度上是憑感覺決定的,一緻性檢驗隻是檢驗 感覺 有沒有自相沖突得太離譜。

引例:

聯考結束,坤坤面臨選擇大學的問題,擺在他面前的選擇有兩個:大學A和大學B。

坤坤覺得,他最關心的有四個方面:學習氛圍,就業前景,男女比例,校園景色,權重分别為0.4,0.3,0.2,0.1。

那麼坤坤要完成的,就是通過調查這兩所學校的上面4個特征名額,對其進行打分,完成下表:

權重 大學A 大學B
學習氛圍 0.4
就業前景 0.3
男女比例 0.2
校園景色 0.1

最終,經過坤坤百度以及各種調查,打分如下(要求同一特征不同大學分數之和為1):

權重 大學A 大學B
學習氛圍 0.4 0.6 0.4
就業前景 0.3 0.5 0.5
男女比例 0.2 0.3 0.7
校園景色 0.1 0.2 0.8

經計算:

  • A = 0.4*0.6 + 0.3*0.5 + 0.2*0.3 + 0.1*0.2=0.47
  • B = 0.53

B>A 是以最終小坤去了大學B。

即打分法解決評價問題時,隻需要我們補充完成下面這張表格即可:

權重 方案1 方案2
名額1
名額2
名額3
名額4

同顔色單元格之和為1。

一、層次分析法的例題

題目:

選擇好大學後,坤坤準備在開學前去旅遊,他決定在城市A,城市B,城市C中選擇一個作為目标地點。

請你确定評價名額、形成評價體系來為坤坤同學選擇最佳的方案。

從上面居中的這段話中,很直接得就告訴我們這是一個評價類問題,那麼我們不妨用剛剛學到的層次分析來解決這個問題。

解決評價類問題,大家首先要想到以下三個問題:

  • 我們評價的目标是什麼?
    • 最佳旅遊目标的選擇
  • 我們為了達到這個目标有哪幾種可選的方案?
    • 城市A、B、C
  • 評價的準則或者說名額是什麼?
    • 我們根據什麼東西來評價好壞?

那麼問題來了,對于第三個問題,題目沒給相關資料支撐,比如哪裡的空氣好啊費用低呀... 需要我們查閱相關的資料。

一般而言,前兩個問題的答案很容易得到,第三個問題的答案需要我們根據題目中的背景材料、常識以及網上搜集到的參考資料進行結合,從中篩選出最合适的名額。

這個時候,我們就可以去知網(或者萬方、百度學術、谷歌學術等平台)搜尋相關的文獻,這樣一來,我們的論文也就有文獻引用了,讓我們的資料等看起來有理有據,顯得專業,還能明目張膽地借鑒學習一下他們論文中的觀點。

推薦一個據說很厲害的網站:蟲部落快搜 - 搜尋快人一步

那麼現在,假如我們替坤坤查詢了資料後選擇了以下五個名額:

  • 景點景色
  • 旅遊花費
  • 居住環境
  • 飲食情況
  • 交通便利程度

接下來,要對坤坤如何提問才能幫他做出合理的決定?

這就要用到我們最開始學的那張表了

權重 城市A 城市B 城市C
景色
花費
居住
飲食
交通

但是,如果我們直接問坤坤:權重多少,城市ABC評分多少,會顯得十分片面且不周全(第二天再問他絕對又換了個數,他自己也記不清。)

在确定影響某因素的諸因子在該因素中所占的比重時,遇到的主要困難 是這些比重常常不易定量化。此外,當影響某因素的因子較多時,直接 考慮各因子對該因素有多大程度的影響時,常常會因考慮不周全、顧此 失彼而使決策者提出與他實際認為的重要性程度不相一緻的資料,甚至 有可能提出一組隐含沖突的資料。

——選自司守奎[kuí]老師的《數學模組化算法與應用》

是以,我們采用分而治之的思想,先來處理權重吧~

問題:

  • 一次性考慮這五個名額之間的關系,往往考慮不周。

解決方法:

  • 兩個兩個名額進行比較,最終根據兩兩比較的結果來推算出權重。

1.1 兩兩比較獲得判斷矩陣

簡單來說就是我們這5個名額分别比較,比如我覺得:景色比花費更重要,飲食比交通非常重要... 通過這樣的方式對不同的重要程度指派 并 最後計算,進而得到權值。

标度 含義
1 表示兩個因素相比,具有同樣重要性
3 表示兩個因素相比,一個因素比另一個因素稍微重要
5 表示兩個因素相比,一個因素比另一個因素明顯重要
7 表示兩個因素相比,一個因素比另一個因素強烈重要
9 表示兩個因素相比,一個因素比另一個因素極端重要
2,4,6,8 上述兩相鄰判斷的中值如2是1和3之間
倒數 A和B相比如果标度為3,那麼B和A相比就是1/3

接下來,就是兩兩比較五個名額對于選擇最終的旅遊景點的重要性。

我們繪制如下表格,其對角線肯定都為1:

景色 花費 居住 飲食 交通
景色 1
花費 1
居住 1
飲食 1
交通 1

問:景色和花費相比的重要程度?

坤:我認為景色比花費略重要,介于同等重要1和稍微重要3之間吧。

問:景色和居住相比的重要程度?

坤: 我認為景色比居住要重要一點,介于稍微重要3和明顯重要5之間吧。

景色 花費 居住 飲食 交通
景色 1 2 4
花費 1/2 1
居住 1/4 1
飲食 1
交通 1

這樣坤坤回答完10次( 

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

),填完了這張用于計算權重的表格(重要性更加穩定精确了):

景色 花費 居住 飲食 交通
景色 1 2 4 3 3
花費 2 1 7 5 5
居住 1/4 1/7 1 1/2 1/3
飲食 1/3 1/5 2 1 1
交通 1/3 1/5 3 1 1

注:實際情況下沒有坤坤幫我們回答,層次分析法中這張表是交給‘專家’ 填的,具體我們等後面再說。(其實我們自己憑感覺填,在論文中不說怎麼來的也行,後面會有獲獎案例鑒賞。)

這樣,我們所形成的正互反矩陣,就是層次分析法中的判斷矩陣。

得到判斷矩陣,我們就可以計算出權重了,方法後面再講。 

同理,我們可以得到城市A、B、C在景色、花費、居住、飲食、交通所占的權重(得分),是以需要再填5張表格,如問完了坤坤對于城市ABC中景色的看法:

景色 城市A 城市B 城市C
城市A 1 2 5
城市B 1/2 1 2
城市C 1/5 1/2 1

其它關于花費、居住、飲食、交通的表我就略了。

注:一個可能出現問題的地方:

坤坤:我覺得x比y好,y比z好,z比x好或一樣好。

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

如果把語氣加重一些,誰比誰非常好,那麼這種不一緻的現象會更加嚴重。

1.2 一緻性正互反矩陣的引入

此時,我們就要介紹一個東西:一緻矩陣,用它來判斷資料知否合理。

  • 若矩陣中每個元素 
    【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示
     且滿足 
    【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示
    ,則我們稱該矩陣為正互反矩陣。
  • 在層次分析法中,我們構造的判斷矩陣均是正互反矩陣。
  • 若正互反矩陣滿足 
    【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示
    ,則我們稱其為一緻矩陣。
1 2 4
1/2 1 2
1/4 1/2 1

你看,上面這個矩陣就是一緻矩陣。

比如我讓i=1, j=2, k=3, 那麼2*2=4:

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

 令i=2, j=2, k=1, 那麼1*1/2=1/2:

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

此外除了 

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

一緻矩陣還有個特點,就是行或列對應成比例。

我們引入一緻矩陣,用來檢驗我們構造的判斷矩陣和一緻矩陣是否有太大的差别。

景色(原始) 城市A 城市B 城市C
城市A 1 2 5
城市B 1/2 1 2
城市C 1/5 1/2 1
景色(一緻矩陣) 城市A 城市B 城市C
城市A 1 2 4
城市B 1/2 1 2
城市C 1/4 1/2 1
引理:n階正反矩陣A為一緻矩陣時當且僅當最大特征是 
【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

;

           且當正反矩陣A非一緻時,

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示
景色 城市A 城市B 城市C
城市A 1 2 a
城市B 1/2 1 2
城市C 1/a 1/2 1
【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

從上圖我們可以發現,當a=4也就是上方剛開始介紹的一緻矩陣,此時最大特征值最小,為3=n也就是矩陣的階數。若a不為4,或a離4越來越遠,不一緻現象越明顯,則其特征值也遞增。

1.2.1 一緻性檢驗的步驟

1. 計算一緻性名額CI

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

2. 查下表找對應的平均随機一緻性名額RI

n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
R 0.52 0.89 1.12 1.26 1.36 1.41 1.46 1.49 1.52 1.54 1.56 1.58 1.59

注:在實際運用中,n很少超過10,如果名額的個數大于10,則可考慮建立 二級名額體系,或使用我們以後要學習的模糊綜合評價模型。

3. 計算一緻性比例CR

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

如果CR < 0.1,  則可認為判斷矩陣的一緻性可以接受;

否則需要對判斷矩陣進行修正。

1.3 根據一緻性正互反矩陣計算權重 

以下表為例,雖然不是一緻矩陣,但它的CR<0.1,我們選擇接受不做調整。

(CR>0.1如何調整在後面)。

景色 城市A 城市B 城市C
城市A 1 2 5
城市B 1/2 1 2
城市C 1/5 1/2 1

我們取出第一列,做歸一化處理(城市ABC對于城市A的重要性是1、1/2、1/4)。

  • 城市A = 1 /(1+0.5+0.2) = 0.5882 
  • 城市B = 0.5/(1+0.5+0.2) = 0.2941
  • 城市C = 0.2/(1+0.5+0.2) =  0.1177

之後我們拿出二三列重複上面操作:

  • 城市A = 2 /(2+1+0.5) =  0.5714 
  • 城市B = 1/(2+1+0.5) =  0.2857
  • 城市C = 0.5/(2+1+0.5) =  =  0.1429
  • 城市A = 5 /(5+2+1) = 0.625 
  • 城市B = 2/(5+2+1) =  0.25
  • 城市C = 1/(5+2+1) =   0.125

這樣我們得到三組權重:

法1:算術平均求權重:

  1. 第一步:将判斷矩陣按照列歸一化 (每一個元素除以其所在列的和)
  2. 第二步:将歸一化的各列相加(按行求和)
  3. 第三步:将相加後得到的向量中每個元素除以n即可得到權重向量 
  • 城市A = (0.5882+0.5714+0.625)/3=0.5949
  • 城市B = (0.2941+0.2857+0.25)/3=0.2766
  • 城市C = (0.1177+0.1429+0.125)/3=0.1285

法2:幾何平均法求權重

  1. 第一步:将A的元素按照行相乘得到一個新的列向量
  2. 第二步:将新的向量的每個分量開n次方
  3. 第三步:對該列向量進行歸一化即可得到權重向量
  • 城市A = 0.5954
  • 城市B = 0.2764
  • 城市C = 0.1283

法3:特征值法求權重

假如我們的判斷矩陣一緻性可以接受,那麼我們可以仿照一緻矩陣權重的求法。 

一緻矩陣有一個特征值為n,其餘特征值均為0。

  1. 第一步:求出矩陣A的最大特征值以及其對應的特征向量
  2. 第二步:對求出的特征向量進行歸一化即可得到我們的權重
景色 城市A 城市B 城市C
城市A 1 2 5
城市B 1/2 1 2
城市C 1/5 1/2 1

該表最大特征值為3.0055,一緻性比例CR=0.0053,對應的特征向量:[-0.8902,-0.4132,-0.1918],對其進行歸一化:[0.5954,0.2764,0.1283]

算術平均法 幾何平均法 特征值法
城市A 0.5949 0.5954 0.5954
城市B 0.2766 0.2764 0.2764
城市C 0.1285 0.1283 0.1283

我們大多數情況下使用特征值法,将其帶入初始要填的表:

權重 城市A 城市B 城市C
景色 0.5954 0.2764 0.1283
花費
居住
飲食
交通

同理這些空着的地方都可以使用同樣的方式。

此時,我們終于得到了這個判斷矩陣:

權重 城市A 城市B 城市C
景色 0.2636 0.5954 0.2764 0.1283
花費 0.4758 0.0819 0.2363 0.6817
居住 0.0538 0.4286 0.4286 0.1429
飲食 0.0981 0.6337 0.1919 0.1744
交通 0.1087 0.1667 0.1667 0.6667

城市A最終得分:0.299

城市B最終得分:0.245

城市C最終得分:0.455

是以最後去城市C旅遊。

二、層次分析法

層次分析法(The Analytic Hierarchy Process即 AHP)是由美國運籌學家、 匹茲堡大學教授T . L. Saaty于20世紀70年代創立的一種系統分析與決策的綜合 評價方法,是在充分研究了人類思維過程的基礎上提出來的,它較合理地解 決了定性問題定量化的處理過程。

AHP的主要特點是通過建立遞階層次結構,把人類的判斷轉化到若幹因 素兩兩之間重要度的比較上,進而把難于量化的定性判斷轉化為可操作的重 要度的比較上面。在許多情況下,決策者可以直接使用AHP進行決策,極大 地提高了決策的有效性、可靠性和可行性,但其本質是一種思維方式,它把 複雜問題分解成多個組成因素,又将這些因素按支配關系分别形成遞階層次 結構,通過兩兩比較的方法确定決策方案相對重要度的總排序。整個過程體 現了人類決策思維的基本特征,即分解、判斷、綜合,克服了其他方法回避 決策者主觀判斷的缺點

步驟:

1.分析系統中各因素之間的關系,建立系統的遞階層次結構.

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示
【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

 注意:如果你用到了層次分析法,那麼上面這個層次結構圖要放在你的模組化論文中哦。

2. 對于同一層次的各元素關于上一層次中某一準則的重要 性進行兩兩比較,構造兩兩比較矩陣(判斷矩陣)。

看看優秀論文的做法吧:

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

【2008年國賽B題一等獎】  關于高等教育學費标準的評價及建議

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

【2016年國賽MATLAB創新獎B題】中國人民大學‐小區開放道路通行影響

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

準則層—方案層的判斷矩陣的數值要結合實際來填寫,如果題目中有其他資料, 可以考慮利用這些資料進行計算。

例如:有一個名額是交通安全程度,現在要比較開放小區、半開放小區和封閉小區,而且 你收集到了這些小區車流量的資料,那麼就可以根據這個資料進行換算作為你的判斷矩陣。

3. 由判斷矩陣計算被比較元素對于該準則的相對權重, 并進行一緻性檢驗(檢驗通過權重才能用)

CR<0.1通過後,三種3方法計算權重:算術平均、幾何平均、特征值法。

建議大家在比賽時三種方法都使用

以往的論文利用層次分析法解決實際問題時,都是采用其中某一種方法求權重,而不同的計算方法可能會導緻結果有所偏差。為了保證結果的穩健性,本文采用了三種方法分别求出了權重後計算平均值,再根據得 到的權重矩陣計算各方案的得分,并進行排序和綜合分析,這樣避免了 采用單一方法所産生的偏差,得出的結論将更全面、更有效。

注:

  • 一緻矩陣不需要進行一緻性檢驗,隻有非一緻矩陣的判斷矩陣才需要進 行一緻性檢驗;
  • 在論文寫作中,應該先進行一緻性檢驗,通過檢驗後再計算 權重,視訊中講解的隻是為了順應計算過程
【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

當CR>0.1時如何修正?

名額X 城市A 城市B 城市C
城市A 1 2 1
城市B 1/2 1 2
城市C 1 1/2 1

答:往一緻矩陣上調整,一緻矩陣的行列成倍數關系

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

 是以:

名額X 城市A 城市B 城市C
城市A 1 2 4
城市B 1/2 1 2
城市C 1/4 1/2 1

4. 根據權重矩陣計算最終得分,并進行排序。

三、層次分析法的一些局限性

1. 評價的決策層不能太多,太多的話n會很大,判斷矩陣和 一緻矩陣差異 可能會很大。

    我們上面提到過的RI名額也隻到了15:

n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
R 0.52 0.89 1.12 1.26 1.36 1.41 1.46 1.49 1.52 1.54 1.56 1.58 1.59

2. 如果決策層中名額的資料是已知的,那麼我們如何利用這些資料來使得評價的更加準确呢? 

層次分析法中,實際情況下沒有坤坤幫我們回答,層次分析法中這張表是交給‘專家’ 填的。(誰比誰重要啊,重要程度是幾呀... ),其實我們自己憑感覺填(兩兩比較的結果)。

該方法仍具有較強的主觀性,判斷/比較矩陣的構造在一定程度上是憑感覺決定的,一緻性檢驗隻是檢驗 感覺 有沒有自相沖突得太離譜。 

四、模型拓展

1. 多個準則層: 

與之前做法一樣,不過是多算幾組表格。 

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

2. 準則不對應全部方案:

可以把另一個方案的權重設為0

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

*3. 一個準則隻對應自己的方案

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

我們隻要生成這樣的表即可:

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

先成大的部分的判斷矩陣,再分别處理小的。

感覺這個模型還是很簡單的。如果有不了解的地方可以聯系帥氣的部落客。

五、代碼展示

你要購買一台筆記本電腦,要考慮其:顔值、性能、口碑、重量、保險情況,這5個方面,最終篩選出了3種品牌的電腦。

第一步:

确定了目标層、準則層、方案層後,我們要做的就是填下表:

權重 電腦A 電腦B 電腦C
顔值
性能
口碑
重量
保險情況

第二步:

我們先處理第一列(權重),其判斷矩陣如下。

顔值 性能 口碑 重量 保險情況
顔值 1 1/2 4 3 3
性能 2 1 7 5 5
口碑 1/4 1/7 1 1/2 1/3
重量 1/3 1/5 2 1 1
保險情況 1/3 1/5 3 1 1

matrix = np.array([[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],

                       [1 / 3, 1 / 5, 3, 1, 1]])

下面我就以上面這個判斷矩陣為例子,定義權重類:

代碼1:

  • 隻定義了權重求解類,初始化時要傳入一個判斷矩陣。
  • 往往我們層次分析問題要求解多個判斷矩陣,可以自己在這基礎之上定義一個AHP類,初始化時把全部判斷矩陣都放進去,直接内部計算輸出選擇方案。
import numpy as np

# 計算權重類
# 首先初始化判斷矩陣,檢驗其CR是否<0.1,如果小于則計算權重,否則提示調整矩陣内數值。
class Calculate_weights:

    # 初始化判斷矩陣
    def __init__(self, array):
        self.array = array
        # n為矩陣次元
        self.n = array.shape[0]
        # 矩陣的特征值和特征向量
        self.eig_val, self.eig_vector = np.linalg.eig(self.array)
        # 矩陣的最大特征值
        self.max_eig_val = np.max(self.eig_val)
        # 矩陣最大特征值對應的特征向量
        self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real

        # 矩陣的一緻性名額CI
        self.CI_value = (self.max_eig_val - self.n) / (self.n - 1)
        # 平均随機一緻性名額RI值清單,用于一緻性檢驗。
        self.RI_list = [0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58,
                        1.59]
        # 矩陣的一緻性比例CR
        self.CR_value = self.CI_value / (self.RI_list[self.n - 1])

    # 一緻性判斷 傳回布爾類型
    def test_consist(self):
        # 列印矩陣的一緻性名額CI和一緻性比例CR
        # 進行一緻性檢驗判斷
        if self.n == 2 or self.CR_value < 0.1:  # 二階矩陣或CR值小于0.1,可以通過一緻性檢驗。
            return True
        else:  # CR值大于0.1, 一緻性檢驗不通過。
            print("判斷矩陣的CR值為:" + str(self.CR_value) + ",未通過一緻性檢驗。")
            return False

    # 算術平均法求權重
    def cal_weight_by_arithmetic_method(self):
        # 求矩陣的每列的和
        col_sum = np.sum(self.array, axis=0)
        # 将判斷矩陣按照列歸一化
        array_normed = self.array / col_sum
        # 計算權重向量
        array_weight = np.sum(array_normed, axis=1) / self.n
        # 列印權重向量
        print("算術平均法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight

    # 幾何平均法求權重
    def cal_weight_by_geometric_method(self):
        # 求矩陣的每列的積
        col_product = np.product(self.array, axis=1)
        # 将得到的積向量的每個分量進行開n次方
        array_power = np.power(col_product, 1 / self.n)
        # 将列向量歸一化
        array_weight = array_power / np.sum(array_power)
        # 列印權重向量
        print("幾何平均法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight

    # 特征值法求權重
    def cal_weight_by_eigenvalue_method(self):
        # 将矩陣最大特征值對應的特征向量進行歸一化處理就得到了權重
        array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
        # 列印權重向量
        print("特征值法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight


if __name__ == "__main__":
    # 給出判斷矩陣
    matrix = np.array([[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],
                       [1 / 3, 1 / 5, 3, 1, 1]])
    # 權重對象
    weights_obj = Calculate_weights(matrix)
    if weights_obj.test_consist():
        # 算術平均法求權重
        weight1 = weights_obj.cal_weight_by_arithmetic_method()
        # 幾何平均法求權重
        weight2 = weights_obj.cal_weight_by_geometric_method()
        # 特征值法求權重
        weight3 = weights_obj.cal_weight_by_eigenvalue_method()
           
算術平均法計算得到的權重為:
 [0.26228108 0.47439499 0.0544921  0.09853357 0.11029827]
幾何平均法計算得到的權重為:
 [0.2636328  0.47726387 0.05307416 0.09883999 0.10718918]
特征值法計算得到的權重為:
 [0.26360349 0.47583538 0.0538146  0.09806829 0.10867824]      

很明顯,性能要更重要一些:

【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

是以我們填完了表的第一列:

權重 電腦A 電腦B 電腦C
顔值 0.2636
性能 0.4758
口碑 0.0538
重量 0.0980
保險情況 0.1086

其它列同理。

代碼2: 

  • AHP類,初始化時把全部判斷矩陣都放進去,直接内部計算輸出選擇方案。

總之要學會變通。 

import numpy as np


# 計算權重類
# 首先初始化判斷矩陣,檢驗其CR是否<0.1,如果小于則計算權重,否則提示調整矩陣内數值。
class Calculate_weights:

    # 初始化判斷矩陣
    def __init__(self, array):
        self.array = array
        # n為矩陣次元
        self.n = array.shape[0]
        # 矩陣的特征值和特征向量
        self.eig_val, self.eig_vector = np.linalg.eig(self.array)
        # 矩陣的最大特征值
        self.max_eig_val = np.max(self.eig_val)
        # 矩陣最大特征值對應的特征向量
        self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real

        # 矩陣的一緻性名額CI
        self.CI_value = (self.max_eig_val - self.n) / (self.n - 1)
        # 平均随機一緻性名額RI值清單,用于一緻性檢驗。
        self.RI_list = [0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58,
                        1.59]
        # 矩陣的一緻性比例CR
        self.CR_value = self.CI_value / (self.RI_list[self.n - 1])

    # 一緻性判斷 傳回布爾類型
    def test_consist(self):
        # 列印矩陣的一緻性名額CI和一緻性比例CR
        # 進行一緻性檢驗判斷
        if self.n == 2 or self.CR_value < 0.1:  # 二階矩陣或CR值小于0.1,可以通過一緻性檢驗。
            return True
        else:  # CR值大于0.1, 一緻性檢驗不通過。
            print("判斷矩陣的CR值為:" + str(self.CR_value) + ",未通過一緻性檢驗。")
            return False

    # 算術平均法求權重
    def cal_weight_by_arithmetic_method(self):
        # 求矩陣的每列的和
        col_sum = np.sum(self.array, axis=0)
        # 将判斷矩陣按照列歸一化
        array_normed = self.array / col_sum
        # 計算權重向量
        array_weight = np.sum(array_normed, axis=1) / self.n
        # 列印權重向量
        #print("算術平均法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight

    # 幾何平均法求權重
    def cal_weight_by_geometric_method(self):
        # 求矩陣的每列的積
        col_product = np.product(self.array, axis=1)
        # 将得到的積向量的每個分量進行開n次方
        array_power = np.power(col_product, 1 / self.n)
        # 将列向量歸一化
        array_weight = array_power / np.sum(array_power)
        # 列印權重向量
        #print("幾何平均法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight

    # 特征值法求權重
    def cal_weight_by_eigenvalue_method(self):
        # 将矩陣最大特征值對應的特征向量進行歸一化處理就得到了權重
        array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
        # 列印權重向量
        #print("特征值法計算得到的權重為:\n", array_weight)
        # 傳回權重向量的值
        return array_weight


class AHP:

    def __init__(self, *args):
        self.col = args[0]
        self.row = args[1]
        self.array = args[2:]
        # 初始化最終矩陣
        self.finally_matrix = np.empty((len(self.row),len(self.col),))

    # 生成全部填好後的最終矩陣
    def f_matrix(self):
        # matrix 為每個判斷矩陣,記得注意順序,如權重在第一列。
        col = 0
        row = 0
        for matrix in self.array:
            weights_obj = Calculate_weights(matrix)
            if weights_obj.test_consist():
                # 特征值法求權重
                weight3 = weights_obj.cal_weight_by_eigenvalue_method()
                if col == 0: # 權重的權重放在列(豎着放在第一列)
                    self.finally_matrix[:, col] = weight3
                    col += 1
                else: # 剩下的都放在行(每行橫着放)
                    self.finally_matrix[row, col:] = weight3
                    row += 1

        return self.finally_matrix

    def result(self):
        self.f_matrix()
        res = []
        for i in range(len(self.col)-1):
            tem_res = np.sum(self.finally_matrix[:,0]*self.finally_matrix[:,i+1])
            res.append(tem_res)
        return res



if __name__ == "__main__":
    # 給出判斷矩陣

    col = ['權重', '電腦A', '電腦B', '電腦C']
    row = ['顔值', '性能', '口碑', '重量', '保險']

    weighting = np.array(
        [[1, 1 / 2, 4, 3, 3], [2, 1, 7, 5, 5], [1 / 4, 1 / 7, 1, 1 / 2, 1 / 3], [1 / 3, 1 / 5, 2, 1, 1],
         [1 / 3, 1 / 5, 3, 1, 1]])

    appearance = np.array([[1, 2, 5], [1 / 2, 1, 2], [1 / 5, 1 / 2, 1]])

    performance = np.array([[1, 1 / 3, 1 / 8], [3, 1, 1 / 3], [8, 3, 1]])

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

    weight = np.array([[1, 3, 4], [1 / 3, 1, 1], [1 / 4, 1, 1]])

    insurance = np.array([[1, 1, 1 / 4], [1, 1, 1 / 4], [4, 4, 1]])

    score_result = AHP(col, row, weighting, appearance, performance, public_praise, weight, insurance).result()
    
    print('選擇{}'.format(col[np.argmax(score_result)+1]))
    
           
【數學模型】層次分析一、層次分析法的例題二、層次分析法三、層次分析法的一些局限性四、模型拓展五、代碼展示

選擇電腦C。