運籌學——matlab實現單純形法

abbcdc發表於2020-12-17

引言

這個程式碼較為簡單易懂,並且每一步幾乎都有詳細的註釋,適合初學者,請放心閱讀。
該matlab程式碼解決的是標準線性規劃下的極大值問題,當然,如果你要解決的是極小值問題,稍加修改就ok了。

完整程式碼

function [x_opt,fx_opt,iter] = simplex(A,b,c)
% 單純形法求解標準形線性規劃問題: max cx s.t. Ax=b x>=0
% x_opt,fx_opt,iter(最優解、最優函式值、迭代次數)
format rat %元素使用分數表示
[m,n] = size(A);              %m約束條件個數, n決策變數數
v=nchoosek(1:n,m);
for i=1:size(v,1)
    if A(:,v(i,:))==eye(m)
        ind_B=v(i,:);
    end
end                               %這幾步主要是為了在係數矩陣中隨機選取幾列,每一次都判斷是否為單位矩陣(基矩陣),並得到基矩陣的列索引
ind_N = setdiff(1:n, ind_B);  %非基變數的索引,原理是返回在1:n中出現而不在ind_B即基變數索引中出現的元素,並從小到大排序
ST = [];
iter=0;                          %記錄迭代次數
% 迴圈求解
while true
    x0 = zeros(n,1);
    x0(ind_B) = b;               %初始基可行解,令基變數的位置為方程組右邊係數,非基變數取值為0
    cB = c(ind_B);               %計算cB,即目標函式在基變數處對應的係數
    Sigma = zeros(1,n);          %Sigma為檢驗數向量
    Sigma(ind_N) = c(ind_N) - cB*A(:,ind_N);   %計算檢驗數(非基變數),因為基變數對應的初始檢驗數一定為0
    [~, k] = max(Sigma);         %選出最大檢驗數, 確定進基變數索引k;~表示忽略第一個引數(即最大值),k是索引
    Theta = b ./ A(:,k);         %計算θ(點除,即矩陣中對應元素相除,得到一個新的矩陣)
    Theta(Theta<=0) = 10000;
    [~, q] = min(Theta);         %選出最小θ
    el = ind_B(q);               %確定出基變數在係數矩陣中的列索引el, 主元為A(q,k)
    vals = [cB',ind_B',b,A,Theta];
    vals = [vals; NaN, NaN, NaN, Sigma, NaN];
    ST = [ST; vals];
    disp(ST);
    if ~any(Sigma > 0)           %所有檢驗數都小於0,此基可行解為最優解, any表示存在某個檢驗數>0        
        x_opt = x0;
        fx_opt = c * x_opt;  %算出最優解
        return
    end
    if all(A(:,k) <= 0)          %表示檢驗數這一列每個數都<=0,有無界解
        x_opt = [];
        break
    end
    % 換基
    ind_B(ind_B == el) = k;      %新的基變數索引
    ind_N = setdiff(1:n, ind_B); %非基變數索引
    % 更新A和b
    A(:,ind_N) = A(:,ind_B) \ A(:,ind_N); %基矩陣的逆乘以非基矩陣
    b = A(:,ind_B) \ b;  %基矩陣的逆乘以b
    A(:,ind_B) = eye(m,m);  %基矩陣更新為單位矩陣
    iter=iter+1;
end
end

如果覺得還不錯的話,請給博主點個贊再走,謝謝~

相關文章