实现单纯形方法无限循环

时间:2018-11-10 13:09:45

标签: matlab linear-programming simplex-algorithm

我正在尝试按照我在优化课程中给出的规则来实现单纯形算法。问题是

min c'*x    s.t.
    Ax = b
    x >= 0

假定所有向量均为列,'表示转置​​。该算法还应将解决方案返回到双LP。遵循的规则是:

rules

在此,A_J表示来自A的列,索引为J,x_J,x_K表示向量x的元素,索引分别为J或K。向量a_s是矩阵A的列s。

现在,我不了解该算法如何处理条件x >= 0,但我决定尝试一下并逐步进行。我为此使用Matlab并获得了以下代码。

X = zeros(n, 1);
Y = zeros(m, 1);

% i. Choose starting basis J and K = {1,2,...,n} \ J
J = [4 5 6]  % for our problem
K = setdiff(1:n, J)

% this while is for goto
while 1
    % ii. Solve system A_J*\bar{x}_J = b.
    xbar = A(:,J) \ b

    % iii. Calculate value of criterion function with respect to current x_J.
    fval = c(J)' * xbar

    % iv. Calculate dual solution y from A_J^T*y = c_J.
    y = A(:,J)' \ c(J)

    % v. Calculate \bar{c}^T = c_K^T - u^T A_K. If \bar{c}^T >= 0, we have
    % found the optimal solution. If not, select the smallest s \in K, such
    % that c_s < 0. Variable x_s enters basis.
    cbar = c(K)' - c(J)' * inv(A(:,J)) * A(:,K)
    cbar = cbar'

    tmp = findnegative(cbar)
    if tmp == -1  % we have found the optimal solution since cbar >= 0
        X(J) = xbar;
        Y = y;
        FVAL = fval;
        return
    end

    s = findnegative(c, K)  %x_s enters basis

    % vi. Solve system A_J*\bar{a} = a_s. If \bar{a} <= 0, then the problem is
    % unbounded.
    abar = A(:,J) \ A(:,s)

    if findpositive(abar) == -1  % we failed to find positive number
        disp('The problem is unbounded.')
        return;
    end

    % vii. Calculate v = \bar{x}_J / \bar{a} and find the smallest rho \in J,
    % such that v_rho > 0. Variable x_rho exits basis.
    v = xbar ./ abar
    rho = J(findpositive(v))

    % viii. Update J and K and goto ii.
    J = setdiff(J, rho)
    J = union(J, s)
    K = setdiff(K, s)
    K = union(K, rho)
end

函数findpositive(x)findnegative(x, S)返回x中正或负值的第一个索引。 S是我们要查看的一组索引。如果省略S,则检查整个向量。出于调试目的,省略了分号。

我测试此代码的问题是

c = [-3 -1 -3 zeros(1,3)];
A = [2 1 1; 1 2 3; 2 2 1];
A = [A eye(3)];
b = [2; 5; 6];

zeros(1,3)eye(3)的原因是问题不平等,我们需要松弛变量。我已将起始基准设置为[4 5 6],因为注释指出起始基准应设置为松弛变量。

现在,执行期间发生的情况是,在第一次运行while时,索引为1的变量进入了基数(在Matlab中,索引从1开始),而4退出了基数那是合理的。在第二轮中,2输入基数(因为它是最小的索引,c(idx) < 01离开它。但是现在在下一次迭代中,1输入基数再一次,我知道为什么要输入它,因为它是最小的索引,例如c(idx) < 0。但是这里开始循环了。我认为这本不应该发生,但是按照规则我看不出如何防止这种情况发生。 / p>

我想我对笔记的解释肯定有问题,但是我看不到哪里错了。我还记得当我们在纸上求解LP时,我们每次都在更新主观函数,因为当输入变量时,我们将其从主观函数中删除,并在subj中表示该变量。可以使用等式之一的表达式进行运算,但是我认为这是不同的算法。

任何评论或帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

问题已解决。原来,注释中的第7点是错误的。相反,第7点应该是

enter image description here