单纯形算法、对偶单纯形算法(MATLAB实现)

单纯形算法

这里我用matlab来实现改进单纯形算法(用矩阵来求解)。可以看出,用矩阵描述,相较于单纯形表,过程要简洁得多,核心为用 B − 1 B^{-1} B1来实现求解,

代码如下:

% 单纯形算法--标准形式线性规划问题
% -------------------------------------------------------------------------
% 参数说明:
% c  -- 价值向量(行向量)
% A  -- 系数矩阵
% b  -- 资源向量(列向量)
% x0 -- 初始基可行解
% -------------------------------------------------------------------------
% 返回值说明:
% x  -- 解(列向量)
% resultCase = 1  -- 解为最优解  
% resultCase = -1 -- 解为无界解

function [x, resultCase] = StandardSimplexAlgorithm(c, A, b, x0)

indexB = find(x0 ~=0);
indexN = find(x0 == 0);

while 1
    % 矩阵描述
    B = A(:, indexB);
    N = A(:, indexN);
    x_B = x0(indexB);
    x_N = x0(indexN);
    c_B = c(indexB);
    c_N = c(indexN);

    % 非基变量检验数
    sigmaN = c_N - c_B * inv(B) * N;
    
    % 判断是否为最优解
    if isempty(find(sign(sigmaN) > 0))
        x(indexB) = inv(B) * b;
        x(indexN) = zeros(length(x_N), 1);
        x = x';
        resultCase = 1;
        return;
    end

    % 确定换入变量
    [maxSigma, inputIndex] = max(sigmaN);
    input = indexN(inputIndex);
    P_input = B \ A(:, input);
    
    % 判断是否为无界解
    Pn = B \ A(:, indexN);
    PnCol = size(Pn, 2);
    for i = 1 : PnCol
        if isempty(find(sign(Pn(:, i)) > 0))
            x = [];
            resultCase = -1;
            break;
        end
    end

    % 确定换出变量
    thetaSet = (inv(B) * b) ./ P_input;
    
    thetaSet(thetaSet < 0) = inf;
    [theta, outputIndex] = min(thetaSet((thetaSet > 0))); 
    % 上面这行代码没有考虑到theta中含有负数的情况。如果含有负数,
    % 这样的处理会导致数组min()操作的不是原来的数组,而是缩短之后的数组,这会导致入基变量的索引错误。
    % 故在之前堆thetaSet中的负数做一个预处理,以避免上述情况

    output = indexB(outputIndex);

    % 基变换
    indexN(inputIndex) = output;
    indexB(outputIndex) = input;
end

end

对偶单纯形算法

刚开始我想按照实现改进单纯形算法的思路来实现对偶单纯形算法,但是发现完全用矩阵的话,换入变量无法确定,必须在每一步中对(b A) 进行变换,如同单纯形表算法的过程。

代码如下:

% 对偶单纯形算法
% A -- 系数矩阵
% C -- 决策变量系数矩阵
% b -- 资源向量
% 输入的线性规划问题为原问题(min),且约束条件必须为小于等于型

function x = DualSimplexAlgorithm(C, A, b)

[A_Row, A_Col] = size(A);
A = [-A, eye(A_Row)];
C = [-C, zeros(1, A_Row)];
b = -b;
x = [zeros(1, A_Col), b']; % 初始解


indexB = find(x ~=0); % 基变量索引集合
indexN = find(x == 0); % 非基变量索引集合

while 1
    % 矩阵描述
    B = A(:, indexB);
    N = A(:, indexN);
    x_B = b;
    x_N = zeros(A_Col, 1);
    C_B = C(indexB);
    C_N = C(indexN);
    
    % 判断是否为最优解
    if isempty(find(sign(b) < 0))
        x(indexN) = x_N;
        x(indexB) = x_B;
        x
        fprintf("达到最优解");
        break;
    end
    
    % 确定换出变量
    [min_b, outputIndex] = min(b);
    
    % 判断是否为非可行解
    if isempty(find(sign(A(outputIndex, :)) < 0))
        x = [];
        fprintf("无可行解");
        break;
    end
    
    % 确定换入变量
    sigmaN = C_N - C_B * B * N;
    thetaSet = sigmaN ./ A(outputIndex, indexN);
    thetaSet(thetaSet < 0) = inf;
    [theta, inputIndex] = min(thetaSet);
    input = indexN(inputIndex);
    
    % 矩阵迭代
    b(outputIndex) = b(outputIndex) / A(outputIndex, input);
    A(outputIndex, :) = A(outputIndex, :) ./ A(outputIndex, input);    
    for i = 1 : A_Row
        if i ~= outputIndex
            b(i) = b(i) - b(outputIndex) * A(i,  input) / A(outputIndex, input);
            A(i, :) = A(i, :) - A(outputIndex, :) .* (A(i, input) / A(outputIndex, input));
        end
    end
    
    % 基变换
    output = indexB(outputIndex);
    indexN(inputIndex) = output;
    indexB(outputIndex) = input;
end

end

你可能感兴趣的:(最优化方法)