本章會介紹如何利用非線性規劃解決選址問題,這個問題是文章線性規劃在數學建模中的兩道例題中第二道投料問題的第二小題,本章為基於這道題的基礎上進行介紹,建議讀者返回去看一看
目錄
- 一、問題提出
- 二、問題分析
- 三、模型建立
- 四、程式碼實現
- 1.輸入目標函式
- 2.輸入線性約束
一、問題提出
二、問題分析
第二小問的目標函式其實與第一小問的一樣,都是求噸千米數最小。但不同的是,在第一小問的背景下,目標函式僅僅是一個一個ax+bx+....的求和形式,是一個線性規劃。
但第二小問把ai與bi的變成了一個目標變數,就成了一個非線性規劃
三、模型建立
第二小問的模型在第一小問的基礎上新增了4個決策變數,為兩個工地的橫縱座標,此外變成了一個非線性規劃
四、程式碼實現
1.輸入目標函式
相對第一問直接輸入係數向量,輸入目標函式更麻煩,這裡需要把新料場的座標當作目標變數給寫進函式里。這裡也可以用pdist2函式計算兩個座標的距離,但要求都處理成橫向量(也就是說pdist2函式也是可以在函式中處理非數值型的引數)
function f = fun5(xx) % 注意為了避免和下面的x同號,我們把決策變數的向量符號用xx表示(注意xx的長度為16)
a=[1.25 8.75 0.5 5.75 3 7.25]; % 工地的橫座標
b=[1.25 0.75 4.75 5 6.5 7.25]; % 工地的縱座標
x = [xx(13) xx(15)]; % 新料場的橫座標
y = [xx(14) xx(16)]; % 新料場的縱座標
c = []; % 初始化用來儲存工地和料場距離的向量 (這個向量就是我們的係數向量)
for j =1:2
for i = 1:6
c = [c; sqrt( (a(i)-x(j))^2 + (b(i)-y(j))^2)]; % 每迴圈一次就在c的末尾插入新的元素
end
end
% 下面我們要求噸千米數,注意c是列向量,我們計算非線性規劃時給定的初始值x0是行向量
f = xx(1:12) * c;
end
2.輸入線性約束
format long g %可以將Matlab的計算結果顯示為一般的長數字格式(預設會保留四位小數,或使用科學計數法)
% 不等式約束
A =zeros(2,16); % 注意這裡要改成16
A(1,1:6) = 1;
A(2,7:12) = 1;
b = [20,20]';
% 等式約束
Aeq = zeros(6,16); % 注意這裡要改成16
for i = 1:6
Aeq(i,i) = 1; Aeq(i,i+6) = 1;
end
beq = [3 5 4 7 6 11]'; % 每個工地的日需求量
% 上下界
lb = zeros(16,1);
% lb = [zeros(12,1); -inf*ones(4,1)]; 兩個新料場座標的下界可以設為-inf
% 進行求解
% 注意哦,這裡我們只嘗試了這一個初始值,大家可以試試其他的初始值,有可能能夠找到更好的解。
% 未來我會在遺傳演算法中再來看這個例題。
x0 = [3 5 0 7 0 1 0 0 4 0 6 10 5 1 2 7]; % 用第一問的結果作為初始值
[x,fval] = fmincon(@funpp,x0,A,b,Aeq,beq,lb) % 注意沒有非線性約束,所以這裡可以用[]替代,或者乾脆不寫
reshape(x(1:12),6,2)