如何处理线性规划的单纯形算法的特殊情况

时间:2016-01-07 19:51:38

标签: linear-programming simplex-algorithm

这是SO问题的后续问题:Code a linear programming exercise by hand。为了教学目的,我对实现单纯形算法(线性规划)有类似的兴趣。我知道对于单纯形算法的简单实现有很多可能的改进。但我有兴趣开发一个最小的完整单纯形代码。

到目前为止,我发现的最接近的实现是this answer,因为@Pii在matlab中提到了上述问题,为了完整性将其复制到下面。从相对较短的代码中,我可以看到the basic logic of simplex涉及到如何实现旋转(正如@ RamNarasimhan的回答中所指出的那样)。但我不知道如何处理线性编程问题的特殊情况,包括:

  1. 不可行的问题,其中可行区域是空的。

  2. 无限问题,其中目标函数值不受上述限制(对于标准LP格式:即最大化问题)

  3. 我认为处理这两个案例后,单一的实现将完成,因为它可以处理任何LP问题。

    我的问题是如何修改代码来处理这两种特殊情况。

    注意:我不是在寻找完整的代码,只是描述了处理上述两个案例的具体逻辑。我也看了Looking for "simple" integer linear programming source code / pseudo code,但没有找到答案。

    - 由@Pii引起的代码 -

    function [x, fval] = mySimplex(fun, A, B, lb, up)
    
    %Examples paramters to show that the function actually works 
    
    % sample set 1 (works for this data set)
    
    % fun = [8 10 7];
    % A = [1 3 2; 1 5 1];
    % B = [10; 8];
    % lb = [0; 0; 0];
    % ub = [inf; inf; inf];
    
    % sample set 2 (works for this data set)
    
    fun = [7 8 10];
    A = [2 3 2; 1 1 2];
    B = [1000; 800];
    lb = [0; 0; 0];
    ub = [inf; inf; inf];
    
    
    % generate a new slack variable for every row of A 
    
    numSlackVars = size(A,1); % need a new slack variables for every row of A 
    
    % Set up tableau to store algorithm data 
    tableau = [A; -fun];
    
    tableau = [tableau, eye(numSlackVars + 1)];
    
    lastCol = [B;0];
    
    tableau = [tableau, lastCol];
    
    % for convienience sake, assign the following: 
    
    numRows = size(tableau,1);
    numCols = size(tableau,2);
    
    % do simplex algorithm 
    
    % step 0: find num of negative entries in bottom row of tableau 
    
    numNeg = 0; % the number of negative entries in bottom row
    
    for i=1:numCols 
        if(tableau(numRows,i) < 0)
            numNeg = numNeg + 1;
        end
    end
    
    % Remark: the number of negatives is exactly the number of iterations
    % needed in the simplex algorithm 
    
    for iterations = 1:numNeg 
        % step 1: find minimum value in last row 
        minVal = 10000; % some big number 
        minCol = 1; % start by assuming min value is the first element 
        for i=1:numCols
            if(tableau(numRows, i) < minVal)
                minVal = tableau(size(tableau,1), i);
                minCol = i; % update the index corresponding to the min element 
            end
        end 
    
        % step 2: Find corresponding ratio vector in pivot column 
        vectorRatio = zeros(numRows -1, 1);
        for i=1:(numRows-1) % the size of ratio vector is numCols - 1
            vectorRatio(i, 1) = tableau(i, numCols) ./ tableau(i, minCol);
        end 
    
        % step 3: Determine pivot element by finding minimum element in vector
        % ratio
    
        minVal = 10000; % some big number 
        minRatio = 1; % holds the element with the minimum ratio 
    
        for i=1:numRows-1
            if(vectorRatio(i,1) < minVal)
                minVal = vectorRatio(i,1);
                minRatio = i;
            end 
        end 
    
        % step 4: assign pivot element 
    
        pivotElement = tableau(minRatio, minCol);
    
        % step 5: perform pivot operation on tableau around the pivot element 
    
        tableau(minRatio, :) = tableau(minRatio, :) * (1/pivotElement);
    
        % step 6: perform pivot operation on rows (not including last row)
    
        for i=1:size(vectorRatio,1)+1 % do last row last 
            if(i ~= minRatio) % skip over the minRatio'th element of the tableau 
                tableau(i, :) = -tableau(i, minCol) * tableau(minRatio, :) 
                                +  tableau(i,:);
            end
        end
    end 
    
    % Now we can interpret the algo tableau 
    
    numVars = size(A,2); % the number of cols of A is the number of variables 
    
    x = zeros(size(size(tableau,1), 1)); % for efficiency 
    
    % Check for basicity 
    for col=1:numVars
        count_zero = 0;
        count_one = 0;
        for row = 1:size(tableau,1)
            if(tableau(row,col) < 1e-2)
                count_zero = count_zero + 1;
            elseif(tableau(row,col) - 1 < 1e-2)
                count_one = count_one + 1;
                stored_row = row; % store this column for later use 
            end
        end
        if(count_zero == (size(tableau,1) -1) && count_one == 1) % basic case
            x(col,1) = tableau(stored_row, numCols);
        else 
            x(col,1) = 0; % not basic case
        end
    end
    
    % find function optimal value at optimal solution 
    fval = x(1,1) * fun(1,1); % just needed for logic to work here 
    for i=2:numVars 
        fval = fval + x(i,1) * fun(1,i);
    end
    
    
    end
    

0 个答案:

没有答案
相关问题