第一部分:
層次分析法(Analytic Hierarchy Process ,簡稱 AHP )是對一些較為復雜、較為模糊的問題作出決策的簡易方法,它特別適用於那些難於完全定量分析的問題。它是美國運籌學家T. L. Saaty 教授於上世紀 70 年代初期提出的一種簡便、靈活而又實用的多准則決策方法。
人們在進行社會的、經濟的以及科學管理領域問題的系統分析中,面臨的常常是一個由相互關聯、相互制約的眾多因素構成的復雜而往往缺少定量數據的系統。層次分析法為這類問題的決策和排序提供了一種新的、簡潔而實用的建模方法。
運用層次分析法建模,大體上可按下面四個步驟進行:
(i )建立遞階層次結構模型;
(ii )構造出各層次中的所有判斷矩陣;
(iii )層次單排序及一致性檢驗;
(iv )層次總排序及一致性檢驗。
這四個步驟中,前兩個步驟最容易理解,后兩個步驟需要一點時間理解
首先從層次結構模型說起
層次分析法是用來根據多種准則,或是說因素從候選方案中選出最優的一種數學方法
最頂層是我們的目標,比如說選leader,選工作,選旅游目的地
中間層是判斷候選方物或人優劣的因素或標准
選工作時有:發展前途 ,待遇 ,工作環境等
選leader時有:年齡,經驗,教育背景,魅力
在分層以后,為了選出最優候選
給目標層分配值1.000
然后將這一值作為權重,分配給不同因素,對應因素的權重大小代表該因素在整個選擇過程中的重要性程度
然后對於候選方案,每一個標准再將其權重值分配給所有的候選方案,每一方案獲得權重值,來源於不同因素分得的權重值的和
如下圖:(alternative1)0.333=0.250/4(criterion1)+0.250/4(criterion2)+0.250/4(criterion3)+0.250/4(criterion4)
最終獲得的各個方案的的權重值的和依然為1
例如選工作時,待遇所占的比重為0.8, 有工作1,2,3候選, 如果工作1的待遇最高,工作2的待遇次之,工作3最差,則可將0.8的值按0.4,0.3,0.1分給工作1,2,3,
這不就是一個簡單的權重打分的過程嗎?為什么還要層次分析呢。這里就有兩個關鍵問題:
1每個准則(因素)權重具體應該分配多少
2每一個候選方案在每一個因素下又應該獲得多少權重
這里便進入層次分析法的第二個步驟,也是層次分析法的一個精華(構造比較矩陣(判斷矩陣)comparison matrix):
首先解決第一個問題:每個准則(因素)權重具體應該分配多少?
如果直接要給各個因素分配權重比較困難,在不同因素之間兩兩比較其重要程度是相對容易的
現在將不同因素兩兩作比獲得的值aij 填入到矩陣的 i 行 j 列的位置,則構造了所謂的比較矩陣,對角線上都是1, 因為是自己和自己比
這個矩陣容易獲得,我們如何從這一矩陣獲得對應的權重分配呢
這里便出現了一個比較高級的概念,正互反矩陣和一致性矩陣
首先正互反矩陣的定義是:
我們目前構造出的矩陣很明顯就是正互反矩陣
而一致性矩陣的定義是:
這里我們構造出的矩陣就不一定滿足一致性,比如我們做因素1:因素2= 4:1 因素2:因素3=2:1 因素1:因素3=6:1(如果滿足一致性就應該是8:1),我們就是因為難以確定各因素比例分配才做兩兩比較的,如果認為判斷中就能保證一致性,就直接給出權重分配了
到了關鍵部分,一致性矩陣有一個性質可以算出不同因素的比例
這里的w就是我們想要知道的權重,所以通過 求比較矩陣的最大特征值所對應的特征向量,就可以獲得不同因素的權重,歸一化一下(每個權重除以權重和作為自己的值,最終總和為1)就更便於使用了。(實際上寫這篇博客就是因為,重新翻了線代的書才好不容易理解這里的,就想記錄下來)
這里補充一點線性代數的知識:
n階矩陣有n個特征值,每個特征值對應一個n維特征列向量,特征值和特征向量的計算方法這里就省略了,反正書中的程序是直接用matlab 的eig函數求的
這里不能忘了,我們給出的比較矩陣一般是不滿足一致性的,但是我們還是把它當做一致矩陣來處理,也可以獲得一組權重,但是這組權重能不能被接受,需要進一步考量
例如在判斷因素1,2,3重要性時,可以存在一些差異,但是不能太大,1比2重要,2比3 重要,1和3比時卻成了3比1重要,這顯然不能被接受
於是引入了一致性檢驗:
一致性的檢驗是通過計算一致性比例CR 來進行的
當 10 . 0 < CR 時,認為判斷矩陣的一致性是可以接受的,否則應對判斷矩陣作適當修正。
CI的值由判斷矩陣計算獲得,RI的值查表獲得,具體的計算公式這里就略去,重點是理解為什么要做一致性檢驗
接下來解決第二個問題:每一個候選方案在每一個因素下又應該獲得多少權重
這里則需要將不同候選方案,在不同因素下分別比較,具體的比較方法,還是使用比較矩陣,只不過之前准則層的比較矩陣比較的對象是因素,這里比較的是某一因素下,候選方案的優劣, n個因素則需構造出來n個比較矩陣
例如在工作環境的因素下,工作1與工作2相比為 :4:2,工作2與工作3=2:1 工作1:工作3=6:1.,這樣構造一個矩陣,再用之前的一致性矩陣的方法就可以求出一個權重,然后相對應因素(這里是工作環境)所擁有的權值就可以按這個權重比例分配給不同候選物或人。
其他因素同理
至此兩個問題就都得到了解決
最終將每個候選物、人從不同因素獲得的權值求和,就可以得到不同候選對於目標層的權值大小,繼而可以根據值的大小,來選出優劣
對於第一部分的總結:
通過對層次分析法的基本了解,不難發現層次分析法對人們的思維過程進行了加工整理,提出了一套系統分析問題的方法,為
科學管理和決策提供了較有說服力的依據,但很明顯的缺點是,整個分析過程似乎都是依賴於人的主觀判斷思維,一來不夠客觀,二來兩兩比較全部人為完成,還是非常耗費精力的,尤其是當候選方案比較多的時候。
文章的第二部分:
層次分析法的變形應用(也可能本來就是這樣用的,只不過參考書上沒這樣說,外語
論文沒細看)解決最優教練選擇問題
目標:選最優教練
准則: 職業生涯所帶隊伍的勝率
職業生涯所帶隊伍的勝場
從教時長(年)
職業生涯所帶隊伍獲獎狀況(化成分數)
候選: 眾多教練
准則層的比較矩陣好構造 ,作6次兩兩比較,就可以獲得4*4的比較矩陣
問題在於候選層的比較矩陣怎么獲得,有4000個教練的話,得比4000*3999次,這里就不必人為比較了,引入定量的數據用程序控制作比即可
勝率因素下就用勝率兩兩作比構造矩陣,從教時長因素下就用年長來做比
這里又有兩點可以注意:
1.不同因素下數據的量綱和性質不一樣,直接用數據作比來分配,不一定合適,比如勝率越要接近1越難,0.7比勝率0.5 和勝率0.9比0.7 ,后者比值比前者小,這顯然不合適。建模中我們結合了冪函數和對數函數處理。
2.這里的用定量數據作比獲得的矩陣顯然滿足一致性要求,不需要做一致性檢驗(想做還不好做,計算CR的值要有RI,RI的值查表只給出9個,計算4000個教練,需要4000個RI呢)
綜上就對層次分析法完成了定性定量結合的應用,以及對多個候選方案的比較(其實只是就是用程序控制數據作比,我們水平有限,能成功應用該方法已經不容易了)
很遺憾的是比賽時編寫的代碼存放的優盤不慎丟失, 沒有辦法把代碼共享出來, 這里只能將書中的代碼貼出。比賽建模時, 就是在這個代碼基礎上進行修改實現。 只要理解了下列代碼,編寫符合自己需求的程序, 應當是水到渠成的事。
代碼:(對應於文章第一部分選 Leader 的內容):
clc,clear fid=fopen('txt3.txt','r'); n1=6;n2=3; a=[]; for i=1:n1 tmp=str2num(fgetl(fid)); a=[a;tmp]; %讀准則層判斷矩陣 end for i=1:n1 str1=char(['b',int2str(i),'=[];']); str2=char(['b',int2str(i),'=[b',int2str(i),';tmp];']); eval(str1); for j=1:n2 tmp=str2num(fgetl(fid)); eval(str2); %讀方案層的判斷矩陣 end end ri=[0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45]; %一致性指標 [x,y]=eig(a); % matlab eig(a) 返回矩陣的特征值和特征向量, 這里的 x 為矩陣 a 的 n 個特征向量, y 為矩陣 a 的 n 個特征值 lamda=max(diag(y)); % eig 函數返回的 y 是矩陣形式保存的, dig(y) 提取對角線上的n 個特征值到一個數組中, 求出最大特征值 lamda num=find(diag(y)==lamda); % 返回最大特征的索引 w0=x(:,num)/sum(x(:,num)); % x( :num) 為最大特征值所對應的那一列特征向量。 w0 中准則層計算出的 包含歸一化后的n 個權重值 cr0=(lamda-n1)/(n1-1)/ri(n1) for i=1:n1 % 循環 n 個維度, 針對每個維度, 都計算一次方案層的比較矩陣及其權重值 [x,y]=eig(eval(char(['b',int2str(i)]))); lamda=max(diag(y)); num=find(diag(y)==lamda); w1(:,i)=x(:,num)/sum(x(:,num)); cr1(i)=(lamda-n2)/(n2-1)/ri(n2); end cr1, ts=w1*w0, cr=cr1*w0
txt3.txt 中的內容, 前6行為准則層的 6 x 6 比較矩陣, 后 18 行則為 6 個准則下, 各自的 3 x 3 的比較矩陣。
1 1 1 4 1 1/2 1 1 2 4 1 1/2 1 1/2 1 5 3 1/2 1/4 1/4 1/5 1 1/3 1/3 1 1 1/3 3 1 1 2 2 2 3 3 1 1 1/4 1/2 4 1 3 2 1/3 1 1 1/4 1/5 4 1 1/2 5 2 1 1 3 1/3 1/3 1 1/7 3 7 1 1 1/3 5 3 1 7 1/5 1/7 1 1 1 7 1 1 7 1/7 1/7 1 1 7 9 1/7 1 1 1/9 1 1
import org.apache.commons.math3.linear.*; public class MatrixTester { public static void main(String[] args) { // Create a real matrix with two rows and three columns, using a factory // method that selects the implementation class for us. double[][] matrixData = { {1d, 1d, 1d, 4d, 1d, 1d/2d}, {1d, 1d, 2d, 4d, 1d, 1d/2d}, {1d, 1d/2d, 1d, 5d, 3d, 1d/2d }, {1d/4d, 1d/4d, 1d/5d, 1d, 1d/3d, 1d/3d }, {1d, 1d, 1d/3d, 3d, 1d, 1d }, {2d, 2d, 2d, 3d, 3d, 1d }, }; RealMatrix m = MatrixUtils.createRealMatrix(matrixData); // One more with three rows, two columns, this time instantiating the // RealMatrix implementation class directly. double[][] matrixData2 = {{1d, 2d}, {2d, 5d}, {1d, 7d}}; RealMatrix n = new Array2DRowRealMatrix(matrixData2); // Note: The constructor copies the input double[][] array in both cases. // Now multiply m by n // RealMatrix p = m.multiply(n); // System.out.println(p.getRowDimension()); // 2 // System.out.println(p.getColumnDimension()); // 2 // // // Invert p, using LU decomposition // RealMatrix pInverse = new LUDecomposition(p).getSolver().getInverse(); RealMatrix D = new EigenDecomposition(m).getD(); RealMatrix V = new EigenDecomposition(m).getV(); for(int i=0; i<D.getRowDimension();i++) { System.out.println(D.getRowMatrix(i)); } for(int i=0; i<V.getRowDimension();i++) { System.out.println(V.getRowMatrix(i)); } // 特征值 double maxLamda; int columIndexForMaxLamda=0; maxLamda=D.getEntry(0,0); for(int i =0, j=0; i<D.getRowDimension()&&j<D.getColumnDimension();i++,j=i) { double lamda = D.getEntry(i,j); if(maxLamda<lamda) { maxLamda=lamda; columIndexForMaxLamda = j; } System.out.println(lamda); } // 輸出尚未做歸一化 w1, w2, w3, w4, w5, w6 , System.out.println(V.getColumnMatrix(columIndexForMaxLamda)); } }