数学建模-层次分析法matlab示例(包含一致性纠错)

步骤

1. 建立层次结构模型

分为最高层、中间层(可以有多层)和最底层。

  • 最高层:决策目的,要解决的问题
  • 中间层:考虑的因素,决策准则
  • 最底层:决策的备选方案

2. 构造判断矩阵

打分依据(两两比较打分,来减少主观的影响):

打分程度
1同样重要
3稍微重要
5明显重要
7强烈重要
9极端重要
2,4,6,8处于对应程度中间

3. 层次单排序及其一致性检验

单排序,对应于中间层对最高层的判断矩阵(1个)
排序:见程序
一致性检验
(n为判断矩阵的维度)

C I = ( λ m a x − n ) ( n − 1 ) CI = \frac {(\lambda_{max} - n)} {(n - 1)} CI=(n1)(λmaxn)

C R = C I R I CR = \frac {CI} {RI} CR=RICI

其中 RI 为 修正因子,具体数值为

矩阵阶数123456789101112131415
RI000.520.891.121.261.361.411.461.491.521.541.561.581.59

R I < 0.1 RI < 0.1 RI<0.1,那么说明该矩阵一致性可以接受

4. 层次总排序及其一致性检验

总排序,对应于最底层对于中间层(一般有多个)
排序:见程序
一致性检验

C R = c r ∗ w 0 CR = cr * w0 CR=crw0

cr:该层每个判断矩阵的CR组成的矩阵
w0:矩阵对应的决策项权重的矩阵(步骤三排序结果)

在一致性检验时,如果一致性检验通过,则直接计算权重,如果一致性检验未通过,则需修正判断矩阵后才计算权重。
修正方式参考论文:[点击这里](https://wenku.baidu.com/view/147d31315a8102d276a22f18.html)

实例

根据景色、费用、居住、饮食、旅途等条件从三个景点中选取最佳的一个

  1. 构建层次结构模型
选择一个目的地
景色 a1
费用 a2
居住 a3
饮食 a4
旅途 a5
目的地1 b1
目的地2 b2
目的地3 b3
  1. matlab程序
file = fopen('D:/DD/数学建模/层次分析法/data.txt'); % 此处修改路径
x= input('请输入决策量数目和方案数目:');
m = x(1);
n = x(2);
a = [];
% 获取中间层判断矩阵
for i = 1:m
    tmp = str2num(fgetl(file));
    a = [a;tmp];
end
for i = 1:m
    str1 = char(['b', num2str(i), '=[]']);
    str2 = char(['b', num2str(i), '=[b', num2str(i), ';tmp]']);
    eval(str1);
    % 获取方案层判断矩阵
    for i = 1:n
        tmp = str2num(fgetl(file));
        eval(str2);
    end
end
RI = [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]; % 一致性修正参数

% 对中间层
disp('中间层:');
[tz, C] = get_feature(a);
% 一致性检验
CI0 = (tz - m)/(m - 1);
CR0 = CI0/RI(m);
W0 = zeros(m, 1);
if CR0 < 0.1
    for i = 1:m
        W0(i, 1) = C(i, 1)/sum(C(:, 1)); %特征向量标准化
    end
    disp('W0:');
    disp(W0);
    disp('此矩阵一致性可以接受。');
else
    disp('此矩阵一致性不可以接受。');
    disp('即将进行修正');
    a = correction(a, m);
    [tz, C] = get_feature(a);
    CI0 = (tz - m)/(m - 1);
    CR0 = CI0/RI(m);
    W0 = zeros(m, 1);
    for i = 1:m
        W0(i, 1) = C(i, 1)/sum(C(:, 1)); %特征向量标准化
    end
    disp(eval(char(["'", 'W', num2str(i), "'"])));
    disp(W1(:, i));
    disp('修正完毕');
end

% 对方案层
disp('方案层:');
W1= zeros(n, m);
for i = 1:m
    [tz, C] = get_feature(eval(char(['b', num2str(i)])));
    CI1 = (tz - n)/(n - 1);
    CR1(i) = CI1/RI(n);
    if CR1(i) < 0.1
        W1(:, i) = zeros(n, 1);
        for j = 1:n
            W1(j, i) = C(j, 1)/sum(C(:, 1)); %特征向量标准化
        end
        disp(eval(char(["'", 'W', num2str(i), "'"])));
        disp(W1(:, i));
        disp('此矩阵一致性可以接受。');
    else
        disp('此矩阵一致性不可以接受。');
        disp('即将进行修正');
        switch i
            case 1
                b1(:, :) = correction(b1, n);
            case 2
                b2(:, :) = correction(b2, n);
            case 3
                b3(:, :) = correction(b3, n);
            case 4
                b4(:, :) = correction(b3, n);
            case 5
                b5(:, :) = correction(b3, n);
            case 6
                b6(:, :) = correction(b3, n);
            case 7
                b7(:, :) = correction(b3, n);
            case 8
                b8(:, :) = correction(b3, n);
            case 9
                b9(:, :) = correction(b3, n);
            case 10
                b10(:, :) = correction(b3, n);
        end
        [tz, C] = get_feature(eval(char(['b', num2str(i)])));
        CI1 = (tz - n)/(n - 1);
        CR0 = CI1/RI(n);
        W1(:, i) = zeros(n, 1);
        for j = 1:n
            W1(j, i) = C(j, 1)/sum(C(:, 1)); %特征向量标准化
        end
        disp(eval(char(["'", 'W', num2str(i), "'"])));
        disp(W1(:, i));
        disp('修正完毕');
    end
end
disp(W1);
% 结果
ts = W1 * W0;
CR = CR1 * W0;
disp('CR:');
disp(CR);
disp('最终方案层的权重:');
disp(ts);



function [tz, C] = get_feature(a)
% 求特征向量和最大特征值

    [V, D] = eig(a); %获取特征值V,特征向量D
    tz = max(diag(D)); %最大特征值
    [~, col] = find(D == tz); %寻找最大特征值的位置
    C = V(:, col); %对应特征向量
end


function A = correction(a, m)
% 判断矩阵一致性修正
% a:判断矩阵
% m:判断矩阵维数
    b = a;
    [~, C] = get_feature(a);
    RI = [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]; % 一致性修正参数
    while 1
        % 列向量归一化
        for i = 1:m
            for j = 1:m
                b(j, i) = a(j, i)/sum(a(:, i));
            end
        end
        % 寻找最小夹角余弦(最大误差的列)
        min = 1; % 存储最小夹角余弦
        r = 1;
        for i = 1:m
            tmp = dot(C, b(:, i))/abs((norm(b(:, i)) * norm(C)));
            if tmp < min
                min = tmp;
                r = i; 
            end       
        end
        % 修正值
        lambda = 0.95; % 经验数值,0.9-1之间最好
        % 列
        for i = 1:m
           a(i, r)  = a(i, r).^lambda * (C(i)/C(r)).^(1-lambda);
        end
        % 行
        for j = 1:m
           a(r, j)  = a(r, j).^lambda * (C(r)/C(j)).^(1-lambda);
        end

        % 验证
        [tz, C] = get_feature(a);
        CI = (tz - m)/(m - 1);
        CR = CI/RI(m);
        disp(CR);
        if CR < 0.1
            A = a;
            break
        end
    end
end

data.txt文件内容:

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 2 5
1/2 1 2
1/5 1/2 1
1 1/3 1/8
3 1 1/3
8 3 1
1 1 3
1 1 3
1/3 1/3 1
1 3 4
1/3 1 1
1/4 1 1
1 1 1/4
1 1 1/4
4 4 1

运行结果:
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值