數學建模 最優化方法:動態規劃 學習筆記

動態規劃簡介

動態規劃是求解多階段決策問題的一種最優化方法。多階段決策過程是指這樣一類特殊的決策問題:由問題的特性可將整個決策過程按時間、空間等標誌劃分爲若干相互關聯又相互區別的階段。在它的每一個階段都需要做出決策,從而使整個過程達到最好的效果。由於各階段決策間有機地聯繫,本階段的決策會影響到下一段的決策。所以在作決策時不僅要考慮本階段最優,還要考慮對最終目標的影響。

遞歸算法

算法描述:
首先要明確的是問題可以分爲幾個階段,分階段的依據可以是時間,空間或者邏輯關係,例如將10枚金幣分給4個商人這個過程,可以先把金幣分給商人Tony,再在剩下的錢裏面分一部分給Steven,再依次給Bruce和Jimmy,這樣就構造出了簡單的邏輯關係。階段確定之後再看每個階段所有可能的狀態,用k表示階段的序號,sk表示該階段的狀態,Sk表示階段k所有可能狀態的集合。決策就是對於階段k所處的狀態sk進行的操作,記作uk(sk),對應的Dk(sk)是該階段所能採取的策略集合。策略則是該過程依次進行的所有決策的集合p1n{u1(s1),u2(s2),…un(sn)},所有可選的策略集合爲P1n.
狀態轉移方程:動態規劃中本階段的狀態是上一階段狀態和上一階段的決策結果。如果給定了第k階段的狀態 ,本階段決策 ,則第k+1階段的狀態 也完全確定,關係爲 sk+1=Tk(sk,uk)稱爲狀態轉移方程。
指標函數:
用於衡量所選定策略優劣的數量指標稱爲指標函數,它分爲階段指標函數和過程指標函數兩種。階段指標是指k階段 從狀態sk 出發,採用決策uk 時的效益,用 d(sk,uk)表示。對於任意一個給定的k,從第k階段到第n階段的過程稱爲一個原過程的後部子過程。V1n(s1,p1n)表示初始狀態爲 採用策略p1n時原過程的指標函數值。
最優指標函數
記爲 fk(sk),它表示從第k階段狀態 採用最優策略pkn 到過程終止時的最佳效益值。當k=1時,是從初始狀態到全過程結束時整體最優函數。
核心算法可用以下公式描述:在這裏插入圖片描述
舉例如下:
在這裏插入圖片描述
這是動態規劃的經典例題:求A->E最短路徑,而且形式十分簡單,階段也比較明顯:5個階段A->B->C->D->E。接下來用遞推算法加以實現:

clear;clc;
%決策集合利用三維矩陣存儲
Data=zeros(5,5,4);
Data(1,1:3,1)=[3 2 1];
Data(1:3,1:2,2)=[4 3;1 3;3 5];
Data(1:2,1:3,3)=[2 5 3;1 4 2];
Data(1:3,1,4)=[3;1;5];
Len=zeros(4,4);%路徑長度
Route=zeros(5,5,4);%路徑記錄
choice=[1 3 2 3];%每個階段可選操作數量
%開始
for i=4:-1:1
    if i==4
        for j=1:choice(i)
            Len(i,j)=Data(j,1,4);
            Route(j,1,i)=1;
        end
    else
        for j=1:choice(i)
            Len(i,j)=min(Data(j,1:choice(i+1),i)+Len(i+1,1:choice(i+1)));
            ind=find((Data(j,1:choice(i+1),i)+Len(i+1,1:choice(i+1)))==Len(i,j));
            Route(j,ind,i)=ones(size(ind));
        end
        
    end
end
way=[];
ind=2;
way(end+1)=ind;
%從路徑記錄中讀出路徑
for i=2:4
    ind=find(Route(ind,1:choice(i),i)==1);
    way(end+1)=ind;
end
        

結果

Len =

     8     0     0     0
     7     6     8     0
     5     4     0     0
     3     1     5     0
way =

     2     1     1     1

從A開始的最短路徑爲8,從B1開始的最短路徑爲7,從B2開始的最短路徑爲6,依此類推。具體路徑爲A->B2->C1->D1->E。分的階段再多一些,每個階段的可能狀態在多一些,枚舉算法將會計算所有可能路徑的長度,每條路徑的節點數量爲階段數k,然後從中取最小。該算法雖然計算路徑的數量,但每條路徑的節點數量都是2。而且當走到B1點的時候不必再向下一一探索,直接選擇已經求出的最短路徑即可。
從上面的算法描述可以很快判斷出這就是遞歸算法,針對下面一道更經典,更容易的例題,分別用遞歸與遞推來實現:
在這裏插入圖片描述
遞歸:

global Route;%路線記錄
global Data;%數據集
global Flag;%路徑長度記錄,同時也是是否再次需要計算的一個標誌
global sum;%計算次數
sum=0;
Data=[13 0 0 0 0;
    11 8 0 0 0;
    12 7 26 0 0;
    6 14 15 8 0;
    12 7 13 24 11];
Route=zeros(size(Data));
Flag=zeros(size(Data));
pyramid(1,1);
for i=1:size(Data,1)
    Route(i,find(Flag(i,:)==max(Flag(i,:))))=1;
end
function Sum=pyramid(i,j)
global Data;
global Flag;
global sum;
if Flag(i,j)>0
	%如果已經計算過以該該點爲起點的最短路程,直接賦值即可,避免重複計算
    Sum=Flag(i,j);
    return;
end
if i==size(Data,1)
	%遞歸返回
     Sum=Data(i,j);
     Flag(i,j)=Sum;
     sum=sum+1;
     return;
else
    Sum=Data(i,j)+max(pyramid(i+1,j),pyramid(i+1,j+1));
    Flag(i,j)=Sum;
    sum=sum+1;
    return;
end

結果(將金字塔都推到左面對齊):

Flag =

    86     0     0     0     0
    57    73     0     0     0
    39    46    65     0     0
    18    27    39    32     0
    12     7    13    24    11
Route =

     1     0     0     0     0
     0     1     0     0     0
     0     0     1     0     0
     0     0     1     0     0
     0     0     0     1     0

遞推:

clear;clc;
Data=[13 0 0 0 0;
    11 8 0 0 0;
    12 7 26 0 0;
    6 14 15 8 0;
    12 7 13 24 11];
Route=zeros(size(Data));
Flag=zeros(size(Data));
n=size(Data,1);
sum=0;
for i=n:-1:1
    for j=1:i
        if i==n
            Flag(i,j)=Data(i,j);
        else
                Flag(i,j)=Data(i,j)+max(Flag(i+1,j),Flag(i+1,j+1));
                sum=sum+1;
        end
    end
end
for i=1:size(Data,1)
    Route(i,find(Flag(i,:)==max(Flag(i,:))))=1;
end

最後一例:將擁有非連續目標函數的線性規劃問題轉爲動態規劃問題(思路和之前算法描述裏面商人分金幣的例子完全一致,不必贅述,直接遞歸實現)
資源分配問題
資源分配問題就是將數量一定的資源恰當地分配給若干個使用者,而使總的目標函數值爲最優。資源分配問題本屬於靜態規劃,但當我們認爲引進時間因素後,可把它們看成是按階段進行的多階段決策問題。
例:某市電信局有4套通信設備,準備分給甲、乙、丙三個地區支局,事先調查了各支局的經營情況,並對各種分配方案作了經濟效益的估計,如表所示其中設備數爲0時的收益,指已有的經營收益,問應如何分配這四套設備,使總的收益爲最大?
在這裏插入圖片描述

clear;clc;
num=[];
[num,out]=resource_distribution(1,num);
function [newnum,out]=resource_distribution(i,num)
if i==4
    out=0;
    newnum=num;
    return;
else
    compare=[];
    NEWNUM=zeros(1,3,length(0:4-sum(num)));
    for k=0:4-sum(num)
        temp=num;
        if i<3
        temp(end+1)=k;
        else 
            temp(end+1)=4-sum(num);
        end
        [temp_num,value]=resource_distribution(i+1,temp);
        NEWNUM(:,:,k+1)=temp_num;
        compare(end+1)=value+profit(i,k+1);
    end
    ind=find(compare==max(compare));
    newnum=NEWNUM(:,:,ind(1));
    out=max(compare);
    return
end
        
function profit=profit(index,num)
A=[38 41 48 60 66;
    40 42 50 60 66;
    48 64 68 78 78];
profit=A(index,num);

結果:

>> out

out =

   164

>> num

num =

     3     0     1

最優分配:給甲3個,給乙0丙

後記

這裏是用matlab進行的算法實現,matlab完全不需要編程起點,直接上手就能用,以上全都是最簡單的單一解,對於具有同樣的最優指標,很可能有多個解,就競賽而言,給出一種可行方案已經足夠,但本着科學的精神,我無法允許自己將如此簡單的題目還做的半吊子!在學習相關數據結構知識後,必將以上垃圾代碼更新。最後想吐槽一下自己,高考不咋地,被分到了數學專業,每天各種定理,計算。前三個學期光顧着搞績點,結果數學基礎知識學了一堆,動手解決問題的能力卻垃圾地不行,寫以上這樣的小程序還調了很久。自己的目前的目標就是往機器學習方面發展,可是沒有人領着入門,只能馬上獨自啃書,門要靠自己打開,我大學不想再後悔一次了。嘴炮說再多也是廢話,這是我第一次,也是最後一次在網絡上表達自己真實的感受,今後只能用行爲來證明自己。

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