用matlab实现交通分布预测方法——增长系数法

本文介绍了如何在Matlab中优化交通分布预测算法,包括增长系数法、平均增长率法、底特律法和福莱特法。作者将代码封装为函数,便于大量调用,并提供了使用说明和测试案例,指出底特律法可能存在数值计算错误。
摘要由CSDN通过智能技术生成

前言

对于我的第一篇文章:Matlab实现交通分布预测方法 —— 增长系数法 | 平均增长率法、底特律法、福莱特法,有不少同学私信我询问关于如何在 matlab 中调用函数、拆分代码以及需要大量调用的问题。于是我便想着把内容做一些优化,放在这篇文章里。

原来那篇文章开头有我写第一次文章时的感慨,每次打开看到感觉和下面相对理性的内容不符。。

增长系数法算法步骤

首先准备条件要有:

  • 现状完整 OD 表
  • 将来 OD 表中各小区发生、吸引交通量及生成总量

算法流程图如下:

算法流程图

matlab 代码

原来那篇文章,我是设置的交互式代码,即需要在命令行手动输入选择的方法。当需要大量使用时,有些不便。于是我把每个方法都封装成一个函数,需要哪个调用即可。

另外有些同学没有 matlab 基础,不知道如何调用函数,可以看我原来那篇文章里的使用说明部分。如果还是有困难,有需求的人多的话,我会出一期视频教程。

平均增长系数法

先上代码:

function [ res,o,d,m,T,Fo,Fd] = func_Average( od_now,U,V )
%FUNC_AVERAGE 平均增长系数法
%  res 为最终预测的od矩阵
%  o,d分别为未来各小区的总吸引量、发生量
%  m为迭代次数,T为未来出行生成总量
%  Fo,Fd分别为最终发生、吸引增长系数值
%  od_now 为现状OD矩阵(n x n) 
%  U为未来各小区发生量,V为未来各小区吸引量,均为行向量。
n=size(od_now,1);     % 小区个数
O = sum(od_now,2)';    % 现状小区发生量
D = sum(od_now,1);    % 现状小区吸引量
% 计算发生增长系数和吸引增长系数
F_o = U ./ O;   F_d = V ./ D;
alpha = 0.03;    % 误差常数
m = 0;     % 记录迭代次数
while true     % 开始循环
    m = m+1;
    % 计算系数
    f = zeros(n);
    for i = 1:n
      for j = 1:n
         f(i,j)=0.5*(F_o(i)+F_d(j)); 
      end
    end
    % 计算新od表
    od_now = f .* od_now;
    % 更新现状O和D
    O = sum(od_now,2)';    
    D = sum(od_now,1);
    % 计算新的发生和吸引系数
    F_o = U ./ O;   F_d = V ./ D;
    % 判断收敛
    if abs([F_o,F_d]-1) <= alpha
       res = od_now;
       o = sum(res,2)';
       d = sum(res,1);
       T = sum(o);
       Fo = F_o;
       Fd = F_d;
       break
    elseif m >= 100
        disp('请注意,迭代已超过100次,下面输出第100次迭代结果。');
        res = od_now;
        o = sum(res,2)';
        d = sum(res,1);
        T = sum(o);
        Fo = F_o;
        Fd = F_d;
        break
    end
end
end

我实现增长,用的是两个矩阵点乘。唯一相较困难的是增长系数放在循环结构里的位置。下面其他方法基本上如法炮制。

底特律法

function [ res,o,d,m,T,Fo,Fd] = func_Detroit( od_now,U,V )
%FUNC_Detroit 平均增长系数法
%  res 为最终预测的od矩阵
%  o,d分别为未来各小区的总吸引量、发生量
%  m为迭代次数,T为未来出行生成总量
%  Fo,Fd分别为最终发生、吸引增长系数值
%  od_now 为现状OD矩阵(n x n) 
%  U为未来各小区发生量,V为未来各小区吸引量,均为行向量。
n=size(od_now,1);     % 小区个数
O = sum(od_now,2)';    % 现状小区发生量
D = sum(od_now,1);    % 现状小区吸引量
% 计算发生增长系数和吸引增长系数
F_o = U ./ O;   F_d = V ./ D;
alpha = 0.03;    % 误差常数
m = 0;     % 记录迭代次数
while true     % 开始循环
    m = m+1;
    % 计算系数
    G = sum(O)/sum(U);  % 生成量增长率的倒数
    f = zeros(n);
    for i = 1:n
      for j = 1:n
         f(i,j)=G*F_o(i)*F_d(j); 
      end
    end
    % 计算新od表
    od_now = f .* od_now;
    % 更新现状O和D
    O = sum(od_now,2)';    
    D = sum(od_now,1);
    % 计算新的发生和吸引系数
    F_o = U ./ O;   F_d = V ./ D;
    % 判断收敛
    if abs([F_o,F_d]-1) <= alpha
       res = od_now;
       o = sum(res,2)';
       d = sum(res,1);
       T = sum(o);
       Fo = F_o;
       Fd = F_d;
       break
    elseif m >= 100
        disp('请注意,迭代已超过100次,下面输出第100次迭代结果。');
        res = od_now;
        o = sum(res,2)';
        d = sum(res,1);
        T = sum(o);
        Fo = F_o;
        Fd = F_d;
        break
    end
end
end

福莱特法

function [ res,o,d,m,T,Fo,Fd] = func_Fratar( od_now,U,V )
%FUNC_Detroit 平均增长系数法
%  res 为最终预测的od矩阵
%  o,d分别为未来各小区的总吸引量、发生量
%  m为迭代次数,T为未来出行生成总量
%  Fo,Fd分别为最终发生、吸引增长系数值
%  od_now 为现状OD矩阵(n x n) 
%  U为未来各小区发生量,V为未来各小区吸引量,均为行向量。
n=size(od_now,1);     % 小区个数
O = sum(od_now,2)';    % 现状小区发生量
D = sum(od_now,1);    % 现状小区吸引量
% 计算发生增长系数和吸引增长系数
F_o = U ./ O;   F_d = V ./ D;
alpha = 0.03;    % 误差常数
m = 0;     % 记录迭代次数
while true     % 开始循环
    m = m+1;
    % 计算系数
    f = zeros(n);
    for i = 1:n
      for j = 1:n
         Li = O(j)/sum((od_now(:,j)' .* F_d));
         Lj = D(i)/sum((od_now(i,:) .* F_o));
         f(i,j)=0.5*(Li+Lj)*F_o(i)*F_d(j); 
      end
    end
    % 计算新od表
    od_now = f .* od_now;
    % 更新现状O和D
    O = sum(od_now,2)';    
    D = sum(od_now,1);
    % 计算新的发生和吸引系数
    F_o = U ./ O;   F_d = V ./ D;
    % 判断收敛
    if abs([F_o,F_d]-1) <= alpha
       res = od_now;
       o = sum(res,2)';
       d = sum(res,1);
       T = sum(o);
       Fo = F_o;
       Fd = F_d;
       break
    elseif m >= 100
        disp('请注意,迭代已超过100次,下面输出第100次迭代结果。');
        res = od_now;
        o = sum(res,2)';
        d = sum(res,1);
        T = sum(o);
        Fo = F_o;
        Fd = F_d;
        break
    end
end
end

测试

用邵春福老师的第二版《交通规划原理》中的例子来测试一下。

测试例子数据

新建一个脚本文件,放进以下代码:

clear;clc
od_now = [17 7 4;
     7 38 6;
     4 5 17;];   % 现状od
U=[38.6 91.9 36]; % 未来各小区发生量
V=[39.3 90.3 36.9]; % 未来各小区吸引量
% [ res,o,d,m,T] = func_Average(od_now, U, V);
% [ res,o,d,m,T] = func_Detroit(od_now, U, V);
[ res,o,d,m,T] = func_Fratar(od_now, U, V);

倒数三行代码是用来调用函数的,想使用哪个方法,就去掉其前面的百分号注释,像现在就是在使用福莱特法。各种方法得到的 res 结果如下:

平均增长系数法测试结果

底特律法测试结果

福莱特法测试结果

除了底特律法外,其他结果和书中非常接近,应该是四舍五入的问题。底特律法的结果我猜测是书中的结果有误,因为我用计算器跟着书上的例子算了一遍,最后一步迭代的时候,书上算错了。

红框部分,用计算器按一下就知道结果不对。计算器的结果和我代码跑出来的结果对得上。

我原来的文章是用的王炜老师的第二版《交通规划》中的算例。可以发现这俩算例数据和步骤一模一样,底特律法结果同样是有问题的,可能是数字太多疏忽了吧。

  • 28
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Douglassssssss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值