网络分析法ANP的Matalab程序源码

来源:百度文库 编辑:神马文学网 时间:2024/04/29 06:09:04
网络分析法ANP的Matalab程序源码(未完待续)
分类:科学技术
用了两周左右的时间,我编写了网络分析法(The Analytic Network Process,ANP)的Matlab源代码(将在下面给出),主要针对王莲芬老师的《网络分析法(ANP)的理论与算法》中的内部依存的递阶层次结构,而且假设 N = 4 的情形,所以如果要使用该程序,需要作修改,如果你不想改,我可以帮忙!
ANP是美国匹兹堡大学的T.L.Saaty 教授于1996年提出了一种适应非独立的递阶层次结构的决策方法,它是在网络分析法(AHP)基础上发展而形成的一种新的实用决策方法。其关键步骤有以下几个:
1 确定因素,并建立网络层和控制层模型。
2 创建比较矩阵。
3 按照指标类型针对每列进行规范化。
4 求出每个比较矩阵的最大特征值和对应的特征向量。
5 一致性检验。如果不满足,则调整相应的比较矩阵中的元素。
6 将各个特征向量单位化(归一化),组成判断矩阵。
7 将控制层的判断矩阵和网络层的判断矩阵相乘,得到加权超矩阵。
8 将加权超矩阵单位化(归一化),求其K次幂收敛时的矩阵。其中第j列就是网络层中各元素对于元素j的极限排序向量。
% 第一个函数
% 矩阵归一化(单位化)
% Unitize 函数开始
function Matrix_Unitize = Unitize(Matrix)
[line,colume] = size(Matrix);
for j = 1:1:colume
fa = 0;
for i = 1:1:line
fa = fa + Matrix(i,j);
end
sum(j) = fa;
end
for j = 1:1:colume
for i = 1:1:line
Matrix_Unitize(i,j) = Matrix(i,j) / sum(j);
end
end
% Unitize 函数结束
% 第二个函数
% 求一个方阵的最大特征值及其对应的特征向量
% MAX_EigenV 函数开始
function [Max_Eigenvector,Max_Eigenvalue] = Max_EigenV(Matrix)
[line,colume] = size(Matrix);
if line ~= colume
message = '矩阵不是方阵,无法求解最大特征值及其对应的特征向量';
disp(message);
return;
end
[Eigenvector Eigenvalue] = eigs(Matrix);
Max_Eigenvalue = Eigenvalue(1);
for i=1:1:line
Max_Eigenvector(i) = Eigenvector(i,1);
end
% MAX_EigenV 函数结束
% 第三个函数(此函数我没有用)
% 根据给定的指标类型对矩阵的列进行规范化
% Standardize 函数开始
function Matrix_Standardize = Standardize(Matrix, IndexType)
% a 是需要规范化的矩阵
% IndexType 是该矩阵各列的指标类型数组
% IndexType(j) = 1    a 的第 j 列是效益型指标
% IndexType(j) = 0    a 的第 j 列是成本型指标
[m n] = size(Matrix);
MAX = max(Matrix);
MIN = min(Matrix);
d = MAX - MIN;
for j=1:1:n
for i=1:1:m
if IndexType(j) == 1    % 效益型指标规范化
Matrix_Standardize(i,j) = (Matrix(i,j) - MIN(j)) / d(j);
elseif IndexType(j) == 0    % 成本型指标规范化
Matrix_Standardize(i,j) = (MAX(j) - Matrix(i,j)) / d(j);
end
end
end
% Standardize 函数结束
% 第四个函数
% 读取一个格式化文件中所有矩阵,连接成归一化的判断矩阵
% 计算最大特征值对应的特征向量,进行一致性检验,构造判断矩阵.
% version 2.0
% 矩阵文件的(*.txt)格式要求(共4条)
% 1 空格开头的行,回车行,注释行(见第3条)在读取时都会被忽略.
%
% 2 每个矩阵要有维数(Dimension)和序号(Sequence),其次序可以颠倒,但是不能缺项,
%   且关键字及其取值要各占一行(共4行,中间可以有空格行或空行),但关键字行尾不能有空格.
%
% 3 竖线"|"是注释标记,要独自占一行,但是不要在有效的矩阵元素行之后加竖线.
%
% 4 矩阵的元素只能用空格分开,每个元素后都可以跟空格,且空格的数量可以是任意多个.
%   但是,需要强调的是,每一行第一个元素的前面不能有空格(参照第1条)!
% JudgementMatrix 函数开始
function [judge_matrix_unitize,flag] = JudgementMatrix(fid)
judge_matrix = 0;
judge_matrix_unitize = 0;
flag = 0; % 判断矩阵构造成功的标志
LineData = IgnoreLine(fid);  % 跳到第一行有效的数据
Count = 0; % 矩阵计数器
Flag1 = 0; % 是否读取矩阵序号的开关
Flag2 = 0; % 是否读取矩阵列数的开关
Flag3 = 0; % 是否读取矩阵行数的开关
Sequence = 0; % 矩阵的序号
Dimension = 0; % 矩阵的阶
DCount = 0; % 同一文件中每个矩阵的阶数下标
LastCount = 0; % 同一文件中上一个矩阵的阶数下标
while( feof(fid) == 0 )
if strcmp(LineData, 'Sequence')
LineData = IgnoreLine(fid);
if LineData == -1
warning('已经到了文件末尾,无数据可读取!');
flag = -1;
return;
end
Sequence = str2num(LineData);
Flag1 = Flag1 + 1;
elseif strcmp(LineData, 'Dimension')
LineData = IgnoreLine(fid);
if LineData == -1
warning('已经到了文件末尾,无数据可读取!');
flag = -1;
return;
end
DCount = DCount + 1;
Dimension(DCount) = str2num(LineData);
LastCount = DCount-1;
if LastCount > 0 && Dimension(DCount) ~= Dimension(LastCount)
flag = -1;
warning('矩阵的维数不等,比较矩阵弄错了吧!');
end
Flag2 = Flag2 + 1;
end
if ( Flag1 > 1 || Flag2 > 1 )
if Flag1 > 1
c = num2str(Sequence);
c = strcat('第',c);
message = strcat(c, '个矩阵的上一个矩阵没有设置维数关键字"Dimension"!');
flag = -1;
warning(message);
return;
elseif Flag2 > 1
c = num2str(Sequence);
c = strcat('第',c);
message = strcat(c, '个矩阵的上一个矩阵没有设置序号关键字"Sequence"!');
warning(message);
flag = -1;
return;
end
elseif ( Flag1 == 0 && Flag2 ==0 )
warning('没有发现矩阵的序号或行数或列数关键字!请参考文件格式要求!');
flag = -1;
return;
elseif ( Flag1 == 1 && Flag2 == 1 )
Matrix = 0;
% 为了读分数矩阵,逐行读取再变为数值类型
for i = 1:1:Dimension(DCount)
LineData = IgnoreLine(fid);
if LineData == -1
warning('已经到了文件末尾,无数据可读取!');
flag = -1;
judge_matrix_unitize = Unitize(Matrix);
return;
end
DoubleLine = str2num(LineData);
[line_DoubleLine,colume_DoubleLine] = size(DoubleLine);
if colume_DoubleLine ~= Dimension(DCount)
flag = -1;
end
for j = 1:1:colume_DoubleLine
Matrix(i,j) = DoubleLine(j);
end
end
if flag == -1
judge_matrix_unitize = Unitize(Matrix);
return;
end
if isreal(Matrix)
Count = Count + 1;
if Sequence ~= Count
c = num2str(Sequence);
c = strcat('文件中编号为',c);
message = strcat(c,'的矩阵的序号没有按照顺序排列!');
warning(message);
end
% 最大特征值及其对应的特征向量
[vector_lmd_max,lmd_max(Count)] = MaxEV(Matrix);
for j = 1:1:Dimension(DCount)
judge_matrix(Count,j) = vector_lmd_max(j);
end
% 一致性检验
CI(Count) = 0; % 一致性指标
% 当矩阵的阶数 n < 3 时,判断矩阵永远具有完全一致性。
if  Dimension >= 3
% 一致性指标
CI(Count) = ( lmd_max(Count) - Dimension(DCount) ) / ( Dimension(DCount) - 1 );
if CI(Count) >= 0.1
c = num2str(Sequence);
c = strcat('第',c);
message = strcat(c,'个矩阵的一致性指标CI不满足条件,建议调整该矩阵元素!');
warning(message);
flag = -1;
break;
end
end
else
c = num2str(Sequence);
c = strcat('第',c);
message = strcat(c, '个矩阵不是实矩阵吧?');
flag = -1;
warning(message);
return;
end
Matrix = 0; % 矩阵清零
Flag1 = 0; % 是否读取矩阵的开关复位
Flag2 = 0; % 是否读取矩阵的开关复位
end
LineData = IgnoreLine(fid);
end
if flag == -1 || Dimension(DCount) ~= Count
flag = -1;
disp('未进行归一化的特征向量');
judge_matrix = judge_matrix'
% 特征向量归一化
disp('归一化的特征向量');
judge_matrix_unitize = Unitize(judge_matrix)
else
flag = 1;
judge_matrix = judge_matrix';
% 判断矩阵归一化
disp('归一化后的特征向量构成的判断矩阵');
judge_matrix_unitize = Unitize(judge_matrix)
end
% JudgementMatrix 函数结束
% 第五个函数
% 忽略一些特定的行
% IgnoreLine 函数开始
function a = IgnoreLine(fid)
a = fgetl(fid);
% 忽略'|'(竖线),' '(空格)开头的行,以及''(回车)行
while isempty(a) || strcmp(a(1), '|') || strcmp(a(1), ' ')
a = fgetl(fid);
end
% IgnoreLine 函数结束
% 第六个函数
% 按如下图所示的方式连接各个矩阵,构造超矩阵
% BB
% DB  DD
%     AD  AA
%         CA  CC
% version 1.0
% SuperMatrix 函数开始
function super = SuperMatrix(BB,DD,AA,CC,DB,AD,CA)
[lineBB, columeBB] = size(BB);
[lineDD, columeDD] = size(DD);
[lineAA, columeAA] = size(AA);
[lineCC, columeCC] = size(CC);
[lineDB, columeDB] = size(DB);
[lineAD, columeAD] = size(AD);
[lineCA, columeCA] = size(CA);
a = vertcat(BB,DB);
b = zeros(lineBB, columeDD); % 补零
c = vertcat(b,DD);
d = horzcat(a,c); % 方阵
e = zeros(lineAD,columeBB); % 补零
f = horzcat(e,AD);
g = vertcat(d,f);
[lined, columed] = size(d);
h = zeros(lined,columeAA); % 补零
i = vertcat(h,AA);
j = horzcat(g,i); % 方阵
k = zeros(lineCA,columed); % 补零
l = horzcat(k,CA);
m = vertcat(j,l);
[linej, columej] = size(j);
n = zeros(linej,columeCC); % 补零
p = vertcat(n,CC);
super = horzcat(m,p); % 超矩阵
% SuperMatrix 函数结束
% 主函数 ANP 开始
function ANP
clc;
% 读取多个数据文件中的比较矩阵,形成归一化的判断矩阵
disp('————从文件 AA.txt 中构造判断矩阵————');
[fid_AA, message] = fopen('AA.txt','r');
if fid_AA == -1
error('!文件打开失败!');
end
[Waa,flag] = JudgementMatrix(fid_AA);
if flag == -1
warning('文件中的比较矩阵有问题,!!!构造失败!!!');
else
disp('!!!构造成功!!!');
end
fclose(fid_AA);
disp('————从文件 BB.txt 中构造判断矩阵————');
[fid_BB, message] = fopen('BB.txt','r');
if fid_BB == -1
error('文件打开失败!');
end
[Wbb,flag] = JudgementMatrix(fid_BB);
if flag == -1
warning('文件中的比较矩阵有问题,!!!构造失败!!!');
else
disp('!!!构造成功!!!');
end
fclose(fid_BB);
disp('————从文件 CC.txt 中构造判断矩阵————');
[fid_CC, message] = fopen('CC.txt','r');
if fid_CC == -1
error('文件打开失败!');
end
[Wcc,flag] = JudgementMatrix(fid_CC);
if flag == -1
warning('文件中的比较矩阵有问题,!!!构造失败!!!');
else
disp('!!!构造成功!!!');
end
fclose(fid_CC);
disp('————从文件 DD.txt 中构造判断矩阵————');
[fid_DD, message] = fopen('DD.txt','r');
if fid_DD == -1
error('文件打开失败!');
end
[Wdd,flag] = JudgementMatrix(fid_DD);
if flag == -1
warning('文件中的比较矩阵有问题,!!!构造失败!!!');
else
disp('!!!构造成功!!!');
end
fclose(fid_DD);
% 由于 Wdb Wad 不是方阵,此处对 Wdb Wad 的一组原始数据进行单位化
disp('————从文件 DB.txt 中构造判断矩阵————');
[fid_DB, message] = fopen('DB.txt','r');
if fid_DB == -1
error('文件打开失败!');
end
[Wdb,flag] = JudgementMatrix(fid_DB);
fclose(fid_DB);
disp('————从文件 AD.txt 中构造判断矩阵————');
[fid_AD, message] = fopen('AD.txt','r');
if fid_AD == -1
error('文件打开失败!');
end
[Wad,flag] = JudgementMatrix(fid_AD);
fclose(fid_AD);
disp('————从文件 CA.txt 中构造判断矩阵————');
[fid_CA, message] = fopen('CA.txt','r');
if fid_CA == -1
error('文件打开失败!');
end
[Wca,flag] = JudgementMatrix(fid_CA);
if flag == -1
warning('文件中的比较矩阵有问题,!!!构造失败!!!');
else
disp('!!!构造成功!!!');
end
fclose(fid_CA);
% 加权矩阵
Wzz = [ 0.6429  0       0       0
0.3571  0.5958  0       0
0       0.4042  0.5223  0
0       0       0.4777  1
];
% % 注意:矩阵 Wzz 也可通过读取文件 ZZ.txt 获得
% % 可以用下面注释掉的代码代替上面的矩阵Wzz
% disp('————从文件 ZZ.txt 中构造判断矩阵————');
% [fid_ZZ, message] = fopen('ZZ.txt','r');
% if fid_ZZ == -1
%     error('文件打开失败!');
% end
% [Wzz,flag] = JudgementMatrix(fid_ZZ);
% if flag == -1
%     warning('!!!文件中的比较矩阵有问题,构造失败!!!');
% else
%     disp('!!!构造成功!!!');
% end
% fclose(fid_ZZ);
% 按照如下形式组合判断矩阵
% W = [
%     Wbb 0   0   0
%     Wdb Wdd 0   0
%     0   Wad Waa 0
%     0   0   Wca Wcc
% ];
% 加权超矩阵的各个元素
Wbb = Wzz(1,1) * Wbb;
Wdd = Wzz(2,2) * Wdd;
Waa = Wzz(3,3) * Waa;
Wcc = Wzz(4,4) * Wcc;
Wdb = Wzz(2,1) * Wdb;
Wad = Wzz(3,2) * Wad;
Wca = Wzz(4,3) * Wca;
% disp('————加权超矩阵!————');
% 组成超矩阵
weighted_supermatrix = SuperMatrix(Wbb,Wdd,Waa,Wcc,Wdb,Wad,Wca);
% 计算加权超矩阵收敛时的无穷次幂
[Wcc_infpower,flag] = PowerConvergence(Wcc);
if flag == 1
D4 = Wcc_infpower;
[lineA columeA] = size(Waa);
IA = eye(lineA,columeA);
D3 = D4 * Wca / ( IA - Waa );
[lineD columeD] = size(Wdd);
ID = eye(lineD,columeD);
D2 = D3 * Wad / ( ID - Wdd );
[lineB columeB] = size(Wbb);
IB = eye(lineB,columeB);
D1 = D2 * Wdb / ( IB - Wbb );
J = zeros(37, 37);
disp('————加权超矩阵的无穷次幂的解————');
weighted_supermatrix_infpower = [ J(1:25,1:37); D1 D2 D3 D4 ]
elseif flag == 0
message = '加权超矩阵不收敛,奇数次幂不存在!';
disp(message);
return;
end
disp('————将加权超矩阵的无穷次幂的解写入 WW.txt 文件中————');
fid_WW = fopen('WW.txt','w+');
if fid_WW == -1
error('文件打开失败!');
end
for i = 1:1:37
for j = 1:1:37
fprintf(fid_WW,'%.4f  ',weighted_supermatrix_infpower(i,j));
end
fprintf(fid_WW,'\r\n');
end
fclose(fid_WW);
disp('————!!!写入成功!!!————');
%  主函数ANP结束
你可以通过这个链接引用该篇文章:http://axywestwind.bokee.com/tb.b?diaryId=14712852