2015年數模B題學習報告

注:這是屬於機理型建模法,坦白說,這種題型難度很大。以下面這道題爲例,它的程序是通過對整個打車系統進行仿真,然後再進行求解,難度不可謂不大。。。其實,我到現在還沒完全看懂這個程序,哭唧唧。。。。在數學建模選題時,我覺得應該儘可能避開這類題。

1. 問題重述

1.1 背景資料與條件

出租車是市民出行的重要交通工具之一,“打車難”是人們關注的一個社會 熱點問題。隨着“互聯網+”時代的到來,有多家公司依託移動互聯網建立了打 車軟件服務平臺,實現了乘客與出租車司機之間的信息互通,同時推出了多種出 租車的補貼方案。

1.2 需要解決的問題

(1)試建立合理的指標,並分析不同時空出租車資源的“供求匹配”程度。 (2)分析各公司的出租車補貼方案是否對“緩解打車難”有幫助。 (3)如果要創建一個新的打車軟件服務平臺,你們將設計什麼樣的補貼方案,並論證其合理性。

2. 建模與求解思路

(1) 首先要找到合理的指標

(2) 採用機理仿真方式對打車的流程中乘客和出租車的行爲進行仿真;

(3) 計算整個打車系統中的指標,優化打車方案,具體實現的主要代碼如下:

%% 出租車補貼方案仿真程序
% 《MATLAB數學建模方法與實踐》(《MATLAB在數學建模中的應用》升級版),北航出版社,卓金武、王鴻鈞編著. 
clc, clear, close all
%% 數據結構設計
% passengers:
% [出發點橫座標,出發點縱座標,目的地橫座標,目的地縱座標,出行里程]
% 即[xs,ys,xd,yd,l]
% taxis
% [出租車位置橫座標,出租車位置縱座標,出租車被佔用里程]
% 即[x_taxi,y_taxi,lo]
r_valid = 2/10;%出租車有效覆蓋半徑
xmax = 111*cos(pi*34/180)*1.4;
ymax = 0.7*111;
xmax = xmax/10;
ymax = ymax/10;
psnger_total = 80;
taxi_total = 152;
%先生成5000個出發點
for i = 1:psnger_total
    passengers(i,:) = gen_passenger();
end
for i = 1:taxi_total
    taxis(i,:) = gen_taxi();
end
figure
scatter(taxis(:,1)*10,taxis(:,2)*10)
xlabel('x(km)')
ylabel('y(km)')
all_B = [];
all_K = [];
for i = 1:200
    %% 首先更新出租車狀態
    lc = taxis(:,3) - 0.01;%出租車被佔用里程
    lc(lc < 0) = 0;
    taxis(:,3) = lc;
    %空車隨機一個方向前進0.01
    valid_lines = find( lc == 0 );
    all_K = [all_K,1-length(valid_lines)/taxi_total]; 
    for m = 1:length(valid_lines)
        k = valid_lines(m);
        while(1)
            degree = 2*pi*rand();%出行方向
            new_x = taxis(k,1) + 0.01.*cos(degree);
            new_y = taxis(k,2) + 0.01.*sin(degree);
            if(new_x>=0 && new_x<=xmax && new_y>=0 && new_y<=ymax)
                taxis(k,1:2) = [new_x,new_y];
                break
            end
        end
    end
    
    %% 乘客加入系統
    add_passengers_total = 4;%round(normrnd(10,3));
    add_passengers = zeros(add_passengers_total,5);
    for n = 1:add_passengers_total
        add_passengers(n,:) = gen_passenger();
    end
    passengers = [passengers;add_passengers];    
    %% 計算各乘客視野內出租車數目  
    for j = 1:length(passengers)  
        p = passengers(j,:);
        if isnan(p(1))
            continue
        end
        temp_taxis = taxis; 
        %被佔用的出租車不參與打車
        invalid_lines = find(temp_taxis(:,3)>0);
        temp_taxis(invalid_lines,:) = nan;
       %% 然後是乘客乘車
        r = sqrt((temp_taxis(:,1)-p(1)).^2+(temp_taxis(:,2)-p(2)).^2);
        taxi_num = find(r<r_valid);%視野範圍內的車輛 
        if isempty(taxi_num)%視野內沒有車,下一位乘客
            continue;
        else
            %隨機選一輛乘坐
            index = round(rand()*(length(taxi_num)-1))+1;
            taxi_num = taxi_num(index);
            taxis(taxi_num,3) = p(5) + sqrt((taxis(taxi_num,1)-p(1))^2+(taxis(taxi_num,2)-p(2))^2);%此乘客p乘坐的出租車被佔用
            taxis(taxi_num,1) = p(3);taxis(taxi_num,2) = p(4);%將其更新到目的地
            passengers(j,:) = nan;%更新乘客狀態,上車的乘客變爲nan,移出系統
        end
    end
        all_B = [all_B,calcu_b(passengers,taxis)];
end
%% 結果可視化
figure
hold on
scatter(taxis(:,1)*10,taxis(:,2)*10,'g*')
legend('初始位置','一段時間後位置')

%20次演化後纔得到平時狀態,故只保留20次之後的數據
pos = (20:length(all_B));
figure
plot((pos-20)/4.5,all_B(pos));
xlabel('時間(分鐘)')
ylabel('數目不平衡度')
figure
plot((pos-20)/4.5,all_K(pos));
xlabel('時間(分鐘)')
ylabel('里程利用率')

figure
res = sqrt( ((all_K-0.66)./0.66).^2 + (all_B-1).^2 );
plot((pos-20)/4.5,res(pos));
xlabel('時間(分鐘)')
ylabel('供需不平衡度')

 

程序的仿真結果如圖 1、圖 2 所示。

圖 1 出租車初始位置

圖 2 評價指標隨時間的變化趨勢圖

3. 點評

本問題如果按照傳統的建模方法, 無論是建模還是求解難度都比較大, 但如果採用元胞自動機思想的仿真法,就可以利用系統的方法對整個系統進行仿真,再通過參數優化得到最佳的補貼。

程序本身雖然還有不少可以改進的地方, 但總的來說, 程序的建模思路清晰, 程序框架和模塊的構造都比較合理, 編程中使用了分節、註釋、變量預定義、函數定義等方法, 使得整個程序既具備良好的功能性,也體現了可讀性、性能提升等程序開發細節 在三天時間內能達到這個水平, 確實不容易。

當然在此基礎上還有不少可以提升、拓展的空間, 比如如何在此程序基礎上結合不同的城市或區域,仿真出更真實的打車情況, 另外,還可以在指標上拓展思路, 比如一個指標還是有些偏面,但既然可以做仿真, 各種指標都可以仿真出來, 對提升整個建模水平還是比較有幫助的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章