Simplex Method

Prerequisite knowledge: Basics of Linear Programming

Introduction

In algorithm contests, the simplex method is often used to solve linear programming problems. However, most linear programming problems encountered in contests have more special structure and can often be reduced to network flow problems. Consequently, the simplex method is not commonly used, and its efficiency is inferior to algorithms designed specifically for network flow problems.

Basic Concepts

Suppose we want to solve the linear programming problem in standard form with nn decision variables and m+nm+n constraints:

min⁡x  z=cTxsubject to Ax=b,x≥0.\begin{aligned} \min_{x}\; & z = c^Tx \\ \text{subject to }& Ax = b, \\ & x \ge 0. \end{aligned}

We may assume that the system of linear equations defined by these mm equality constraints is solvable and that AA has full rank, so rank⁡A=m≤n\operatorname{rank}A = m \le n.

An Example

Before formally describing the steps of the simplex method, we first examine a concrete example to make them easier to understand.

Example

Consider the linear programming problem

max⁡  10x1+12x2+12x3subject to x1+2x2+2x3≤20,2x1+x2+2x3≤20,2x1+2x2+x3≤20,x1,x2,x3≥0.\begin{aligned} \max\; & 10 x_1 + 12 x_2 + 12 x_3 \\ \text{subject to } & x_1 + 2 x_2 + 2x_3 \le 20, \\ & 2x_1 + x_2 + 2x_3 \le 20, \\ & 2x_1 + 2x_2 + x_3 \le 20,\\ & x_1,x_2,x_3 \ge 0. \end{aligned}

Adding slack variables gives its standard form:

min⁡  −10x1−12x2−12x3subject to x1+2x2+2x3+x4=20,2x1+x2+2x3+x5=20,2x1+2x2+x3+x6=20,x1,x2,x3,x4,x5,x6≥0.\begin{aligned} \min\; & -10 x_1 - 12 x_2 - 12 x_3 \\ \text{subject to } & x_1 + 2 x_2 + 2x_3 + x_4 = 20, \\ & 2x_1 + x_2 + 2x_3 + x_5 = 20, \\ & 2x_1 + 2x_2 + x_3 + x_6 = 20,\\ & x_1,x_2,x_3,x_4,x_5,x_6 \ge 0. \end{aligned}

Observe the equality constraints of this problem. They express the variables x4,x5,x6x_4,x_5,x_6 in terms of x1,x2,x3x_1,x_2,x_3. Rearranging the original problem slightly gives

min⁡xi≥0z=0−10x1−12x2−12x3  subject tox4=20−x1−2x2−2x3,x5=20−2x1−x2−2x3,x6=20−2x1−2x2−x3.\begin{array}{rrrrrr} \min_{x_i\ge 0} & z = & 0 & -10x_1 & -12x_2 & -12x_3\;\\ \text{subject to}& x_4 = & 20 & -x_1 & -2x_2 & -2x_3, \\ & x_5 = & 20 & -2x_1 & -x_2 & -2x_3, \\ & x_6 = & 20 & -2x_1 & -2x_2 & -x_3. \\ \end{array}

From this form, it is clear that setting x1=x2=x3=0x_1=x_2=x_3=0 gives a feasible solution of the original problem

x=(0,0,0,20,20,20)T.x = (0,0,0,20,20,20)^T.

with value z=0z=0. For convenience, call the variables set to zero, x1,x2,x3x_1,x_2,x_3, non-basic variables, and call the remaining variables, x4,x5,x6x_4,x_5,x_6, basic variables.

This feasible solution is clearly not optimal. We can increase x1,x2,x3x_1,x_2,x_3 appropriately while keeping x4,x5,x6x_4,x_5,x_6 nonnegative, so the solution remains feasible. Moreover, because the coefficients of x1,x2,x3x_1,x_2,x_3 in the objective function are strictly negative, increasing them decreases the objective value. For example, we can increase x1x_1. To decrease the objective value as much as possible, we should increase x1x_1 as much as possible. To keep the solution feasible, however, we must maintain x4,x5,x6≥0x_4,x_5,x_6\ge 0. Therefore, x1x_1 can be increased at most to

min⁡{201,202,202}=10.\min\left\{\dfrac{20}{1},\dfrac{20}{2},\dfrac{20}{2}\right\} = 10.

The feasible solution is now

x=(10,0,0,10,0,0)T.x = (10,0,0,10,0,0)^T.

Since x1x_1 has become a basic variable, we need to choose a new non-basic variable to return to the initial form (three basic variables expressed in terms of three non-basic variables). Since x5,x6x_5,x_6 are both zero, either can be chosen as the non-basic variable and set to zero. Choose x5x_5 without loss of generality. Also, substitute

x1=10−0.5x5−0.5x2−x3x_1 = 10 - 0.5x_5 - 0.5x_2 - x_3

Substituting this into the original problem rewrites it as

min⁡xi≥0z=−100+5x5−7x2−2x3  subject tox4=10+0.5x5−1.5x2−x3,x1=10−0.5x5−0.5x2−x3,x6=0+x5−x2+x3.\begin{array}{rrrrrr} \min_{x_i\ge 0} & z = &-100& +5x_5 & -7x_2 & -2x_3\;\\ \text{subject to}& x_4 = & 10 & +0.5x_5 & -1.5x_2 & -x_3, \\ & x_1 = & 10 & -0.5x_5 & -0.5x_2 & -x_3, \\ & x_6 = & 0 & +x_5 & -x_2 & +x_3. \\ \end{array}

This returns to the initial form.

Continue examining the current objective function. The coefficient of the non-basic variable x3x_3 is still negative, so we can consider increasing x3x_3. To keep x4,x1,x6≥0x_4,x_1,x_6\ge 0, x3x_3 can be increased at most to

min⁡{101,101}=10.\min\left\{\dfrac{10}{1},\dfrac{10}{1}\right\} = 10.

Note that in the expression for x6x_6, the coefficient of x3x_3 is positive, so no increase of x3x_3 can make x6x_6 negative. This is why the braces in this step contain only two terms. When x3x_3 reaches 1010, both x1,x4x_1,x_4 become zero, so either can be chosen as the new non-basic variable. Choose x4x_4. Then substitute

x3=10+0.5x5−1.5x2−x4x_3 = 10 + 0.5x_5 - 1.5x_2 - x_4

Substituting this into the problem above transforms it into

min⁡xi≥0z=−120+4x5−4x2+2x4  subject tox3=10+0.5x5−1.5x2−x4,x1=0−x5+x2+x4,x6=10+1.5x5−2.5x2−x4.\begin{array}{rrrrrr} \min_{x_i\ge 0} & z = &-120& +4x_5 & -4x_2 & +2x_4\;\\ \text{subject to}& x_3 = & 10 & +0.5x_5 & -1.5x_2 & -x_4, \\ & x_1 = & 0 & -x_5 & +x_2 & +x_4, \\ & x_6 = & 10 & +1.5x_5 & -2.5x_2 & -x_4. \\ \end{array}

Setting x5=x2=x4=0x_5=x_2=x_4=0 lets us read the current feasible solution from this form:

x=(0,0,10,0,0,10)T,x = (0,0,10,0,0,10)^T,

and its corresponding value is z=−120z=-120.

Repeat the previous operation. Since the coefficient of x2x_2 is negative, its value can be increased; but to keep x3,x6x_3,x_6 nonnegative, it can only be increased to

min⁡{101.5,102.5}=4.\min\left\{\dfrac{10}{1.5},\dfrac{10}{2.5}\right\} = 4.

Since the minimum in the braces occurs in the expression for x6x_6, it becomes zero when x2=4x_2=4. Substitute

x2=4+0.6x5−0.4x6−0.4x4x_2 = 4 + 0.6x_5 - 0.4x_6 - 0.4x_4

Substituting this into the problem above rewrites the original problem as

min⁡xi≥0z=−136+1.6x5+1.6x6+3.6x4  subject tox3=4−0.4x5+0.6x6−0.4x4,x1=4−0.4x5−0.4x6+0.6x4,x2=4+1.5x5−2.5x6−x4.\begin{array}{rrrrrr} \min_{x_i\ge 0} & z = &-136& +1.6x_5 & +1.6x_6 & +3.6x_4\;\\ \text{subject to}& x_3 = & 4 & -0.4x_5 & +0.6x_6 & -0.4x_4, \\ & x_1 = & 4 & -0.4x_5 & -0.4x_6 & +0.6x_4, \\ & x_2 = & 4 & +1.5x_5 & -2.5x_6 & -x_4. \\ \end{array}

Setting the non-basic variables x5,x6,x4x_5,x_6,x_4 to zero again gives the current feasible solution

x=(4,4,4,0,0,0)T.x = (4,4,4,0,0,0)^T.

with corresponding value z=−136z=-136.

Since all non-basic variables have positive coefficients in the objective function, the process described above can no longer improve the objective. Thus, the current feasible solution is optimal and the algorithm terminates.

In this example, the algorithm starts from a feasible solution and repeatedly improves the objective function until no further improvement is possible. This is the basic idea of the simplex method.

Basic Feasible Solutions

Since AA has full rank, we can always choose a subset of size mm, B⊆{1,2,⋯ ,n}B\subseteq\{1,2,\cdots,n\}, such that ABA_B is an invertible square matrix. We can then express xBx_B in terms of the remaining variables xNx_N:

xB=AB−1b−AB−1ANxN.x_B = A_B^{-1}b - A_B^{-1}A_Nx_N.

Here, N={1,2,⋯ ,n}∖BN=\{1,2,\cdots,n\}\setminus B; the matrices AB,ANA_B,A_N are the submatrices formed by the columns of AA with labels i∈Bi\in B and i∈Ni\in N, respectively, and the vectors xB,xNx_B,x_N are the subvectors of xx consisting of components with labels i∈Bi\in B and i∈Ni\in N, respectively. If i∈Bi\in B, then xix_i is called a basic variable; otherwise, xix_i is called a non-basic variable. All basic variables together form a basis, denoted in this article by the corresponding label set BB.

“Basis”

The name “basis” can be understood from linear algebra. Let the column vectors of AA span a linear space VV. Then the column vectors corresponding to BB form a basis of VV.

In the expression for the basic variables xBx_B, setting xN=0x_N=0 gives a solution to all equality constraints1

x=(xB,xN)=(AB−1b,0).x = (x_B,x_N) = (A_B^{-1}b,0).

This solution is called a basic solution of the linear programming problem. If it also satisfies all non-negativity constraints, namely x≥0x\ge 0, it is a feasible solution of the original problem and is called a basic feasible solution (BFS). During simplex iterations, the current solution must always remain a basic feasible solution.

Pivoting

Each iteration of the simplex method is called a pivot. In effect, each pivot removes an old basic variable and adds a new basic variable, thereby improving the objective value.

“Pivot”

The name “pivot” can likewise be understood from linear algebra. As described above, the columns corresponding to a basis BB form a basis of the space VV; they therefore correspond to a set of coordinate axes of the space VV under that basis representation. Pivoting is thus the process of rotating one coordinate axis to a new position.

To determine which basic variable to add, express the objective function in terms of the non-basic variables:

cTx=cBTxB+cNTxN=cBTAB−1b+(cNT−cBTAB−1AN)xN.\begin{aligned} c^Tx &= c^T_Bx_B + c^T_Nx_N \\ &= c_B^TA_B^{-1}b + (c_N^T - c_B^TA_B^{-1}A_N)x_N. \end{aligned}

Setting xN=0x_N=0 gives the objective value z=cBTAB−1bz=c_B^TA_B^{-1}b at the current basic feasible solution. The coefficient of the second term represents the change in the objective function when xNx_N changes:

c~N=∂z∂xN=cN−ANT(AB−1)TcB.\tilde c_N = \dfrac{\partial z}{\partial x_N} = c_N - A_N^T(A_B^{-1})^Tc_B.

Since cB−ABT(AB−1)TcB=0c_B - A_B^T(A_B^{-1})^Tc_B = 0, we can define the vector

c~=(c~BT,c~NT)T=c−AT(AB−1)TcB\tilde c = (\tilde c_B^T,\tilde c_N^T)^T = c - A^T(A_B^{-1})^Tc_B

For a feasible basic solution xx, this is the reduced cost of the linear programming problem. A component c~i<0\tilde c_i<0 means that increasing xix_i can improve the objective function. Such a variable must be non-basic and is called the entering variable for this pivot. After the pivot, xix_i becomes basic and is no longer fixed at zero, although it may still be zero.

After choosing the entering variable, we must choose the old basic variable to remove. We only need to determine which current basic variable first becomes zero as xix_i increases. Substitute xN=(xi,xN∖{i})=(xi,0)x_N=(x_i,x_{N\setminus\{i\}})=(x_i,0) into the expression for xBx_B to obtain

xB=AB−1b−AB−1Aixi.x_B = A_B^{-1}b - A_B^{-1}A_ix_i.

Therefore, the maximum amount by which xix_i can be increased is

θ=min⁡{(AB−1b)j(AB−1Ai)j:(AB−1Ai)j>0}.\theta = \min\left\{\dfrac{(A_B^{-1}b)_j}{(A_B^{-1}A_i)_j}:(A_B^{-1}A_i)_j>0\right\}.

The variable that becomes zero first is the basic variable corresponding to the index jj that attains the minimum in this expression, namely xBjx_{B_j}. It is the “bottleneck” in increasing xix_i: increasing xix_i further would make xBjx_{B_j} negative. This variable is the leaving variable for this pivot. The method for determining it is called the minimum ratio test.

Let the entering variable be xix_i and the leaving variable be xi′x_{i'}. After pivoting, the basic variables are xB∖{i}∪{i′}x_{B\setminus\{i\}\cup\{i'\}} and the non-basic variables are xN∖{i′}∪{i}x_{N\setminus\{i'\}\cup\{i\}}.

Termination Conditions

The simplex method starts from a basic feasible solution and repeatedly pivots. The discussion of pivoting in the previous section was not complete because it omitted special cases. Some special cases terminate the algorithm, while others require additional handling.

First, an entering variable may not exist, that is, c~≥0\tilde c\ge 0. Then no method can further improve the optimal value, so the current basic feasible solution is optimal and the algorithm terminates. A rigorous proof uses the complementary slackness conditions. Let y=(AB−1)TcBy=(A_B^{-1})^Tc_B. Throughout the algorithm, xx remains feasible and complementary slackness holds:

xT(c−ATy)=c~Tx=c~BTxB+c~NTxN=0.x^T(c-A^Ty) = \tilde c^Tx = \tilde c_B^Tx_B + \tilde c_N^Tx_N = 0.

Therefore, it suffices for yy to be feasible for the dual problem, namely ATy≤cA^Ty\le c, to conclude that xx and yy are optimal solutions of the primal and dual problems, respectively. This condition is exactly c~≥0\tilde c\ge 0, meaning that no entering variable exists.

“Shadow Price”

The vector y=(AB−1)TcBy=(A_B^{-1})^Tc_B is often called the dual vector. When the basic feasible solution corresponding to BB is optimal for the primal problem, yy is an optimal solution of the dual problem as well. Thus, solving the primal problem by the simplex method also yields an optimal solution to the dual problem. Since yy is the partial derivative of the current value with respect to the constraint constants, namely

∂(cTx)∂b=(AB−1)TcB=y,\dfrac{\partial(c^Tx)}{\partial b} = (A_B^{-1})^Tc_B = y,

It is also called the shadow price.

Second, a leaving variable may not exist, that is, AB−1Ai≤0A_B^{-1}A_i\le 0. Then there is no “bottleneck” during pivoting: we can keep increasing xix_i to improve the objective until it equals −∞-\infty. This means that the given linear programming problem is unbounded, and the algorithm terminates.

Finally, the entering and leaving variables may not be unique. An inappropriate choice may cause too many pivots or even make the algorithm enter a cycle and fail to terminate. Handling these cases is somewhat more complex; some pivot rules are needed to avoid cycles and reduce the number of pivots.

Simplex Tableau

When implementing pivots, we only need to maintain the coefficient matrix of the linear programming problem after each pivot:

T~B=(−zBc~NTxAB−1AN)=(−cBTAB−1bcT−cBTAB−1ANAB−1bAB−1AN).\tilde T_B = \begin{pmatrix} -z_B & \tilde c^T_N \\ x & A_B^{-1}A_N \end{pmatrix} = \begin{pmatrix} -c_B^TA_B^{-1}b & c^T - c_B^TA_B^{-1}A_N \\ A_B^{-1}b & A_B^{-1}A_N \end{pmatrix}.

It corresponds to the linear programming problem:

min⁡x≥0cBTAB−1b+c~NTxN  subject toxB=AB−1b−AB−1ANxN.\begin{array}{rrrr} \min_{x\ge 0} & & c_B^TA_B^{-1}b & + \tilde c_N^Tx_N\; \\ \text{subject to}& x_B = & A_B^{-1}b & - A_B^{-1}A_Nx_N. \end{array}

The matrix T~B\tilde T_B is called the condensed simplex tableau of the linear programming problem with respect to basis BB. Its upper-left entry (T~B)00(\tilde T_B)_{00} is the value of the current solution (with the opposite sign); the quantity in row 00, column ii, (T~B)0i(\tilde T_B)_{0i}, is the reduced cost of the ii-th non-basic variable xNix_{N_i}; the quantity in row jj, column ii, (T~B)j0(\tilde T_B)_{j0}, is the value of the jj-th basic variable xBjx_{B_j}; and AB−1ANA_B^{-1}A_N consists of the coefficients obtained by using the non-basic variables xNx_N to express the basic variables xBx_B.

It is easy to see that all information needed for a pivot can be obtained directly from the condensed simplex tableau. Specifically, one pivot consists of:

  1. Select a column i=1,⋯ ,n−mi=1,\cdots,n-m with (T~B)0i<0(\tilde T_B)_{0i}<0. If no such ii exists, the current solution is optimal, and −(T~B)00-(\tilde T_B)_{00} is the optimal value.
  2. Select a row j=1,⋯ ,mj=1,\cdots,m such that (T~B)ji>0(\tilde T_B)_{ji}>0 and (T~B)j0/(T~B)ji(\tilde T_B)_{j0}/(\tilde T_B)_{ji} is minimal. If no such jj exists, the original problem is unbounded.
  3. Make xNix_{N_i} entering and xBjx_{B_j} leaving, then update the simplex tableau.

Now let us discuss specifically how to update the simplex tableau. Before the update, row jj represents the equation

xBj=(T~B)j0−∑i=1n−m(T~B)jixNi.x_{B_j} = (\tilde T_B)_{j0} - \sum_{i=1}^{n-m}(\tilde T_B)_{ji}x_{N_i}.

To update the tableau, express xN∖{Ni}∪{Bj}x_{N\setminus\{N_i\}\cup\{B_j\}} in terms of xNix_{N_i}, namely:

xNi=(T~B)j0(T~B)ji−1(T~B)jixBj−∑i′≠i(T~B)ji′(T~B)jixNi′.x_{N_i} = \dfrac{(\tilde T_B)_{j0}}{(\tilde T_B)_{ji}} - \dfrac{1}{(\tilde T_B)_{ji}}x_{B_j} - \sum_{i'\neq i}\dfrac{(\tilde T_B)_{ji'}}{(\tilde T_B)_{ji}}x_{N_{i'}}.

Substituting this into the other equations gives

xBj′=((T~B)j′0−(T~B)j′i(T~B)j0(T~B)ji)+(T~B)j′i(T~B)jixBj−∑i′≠i((T~B)j′i′−(T~B)j′i(T~B)ji′(T~B)ji)xNi.x_{B_{j'}} = \left((\tilde T_B)_{j'0} - (\tilde T_B)_{j'i}\dfrac{(\tilde T_B)_{j0}}{(\tilde T_B)_{ji}}\right) + \dfrac{(\tilde T_B)_{j'i}}{(\tilde T_B)_{ji}}x_{B_j} - \sum_{i'\neq i}\left((\tilde T_B)_{j'i'}-(\tilde T_B)_{j'i}\dfrac{(\tilde T_B)_{ji'}}{(\tilde T_B)_{ji}}\right)x_{N_i}.

Row 00 is similar, except that the left side of the equation becomes −z-z. Although the formulas look complicated, the implementation only needs two steps:

  1. Update row jj: let α=(T~B)ji\alpha=(\tilde T_B)_{ji}, set the number in column ii to 11, and divide every number in the row by α\alpha;
  2. Update every row j′≠jj'\neq j: let β=(T~B)j′i\beta=(\tilde T_B)_{j'i}, set the number in column jj to 00, and subtract β\beta times row jj from the entire row.
“Simplex Tableau”

The simplex tableau is the matrix

TB=(−zc~TxAB−1A)=(−cBTAB−1bcT−cBTAB−1AAB−1bAB−1A).T_B = \begin{pmatrix} -z & \tilde c^T \\ x & A_B^{-1}A \end{pmatrix} = \begin{pmatrix} -c_B^TA_B^{-1}b & c^T - c_B^TA_B^{-1}A \\ A_B^{-1}b & A_B^{-1}A \end{pmatrix}.

Compared with the condensed simplex tableau, it has mm additional columns, corresponding respectively to the mm basic variables; the column corresponding to the jj-th basic variable is always eje_j, meaning that in row jj this vector takes the value 11, while in every other row it takes the value 00. Since these columns provide no additional information, they are often omitted when implementing the simplex method, yielding the condensed simplex tableau.

The simplex tableau makes the tableau-update steps easier to understand. Every tableau TBT_B can be obtained by left-multiplying the same matrix T0T_0 by an invertible matrix LBL_B determined by the basis:

TB=(−cBTAB−1bcT−cBTAB−1AAB−1bAB−1A)=(1−cBTAB−1OAB−1)(0cTbA)=LBT0,T_B= \begin{pmatrix} -c_B^TA_B^{-1}b & c^T - c_B^TA_B^{-1}A \\ A_B^{-1}b & A_B^{-1}A \end{pmatrix} = \begin{pmatrix} 1 & -c_B^TA_B^{-1} \\ O & A_B^{-1} \end{pmatrix} \begin{pmatrix} 0 & c^T \\ b & A \end{pmatrix}=L_BT_0,

Thus, these tableaux and T0T_0 can be converted into one another by a sequence of elementary row operations. Therefore, when updating the tableau, it suffices to perform elementary row operations so that the column corresponding to the entering variable becomes eje_j. Transferring these operations to the condensed tableau gives the steps above.

The reference implementation for updating the condensed simplex tableau is as follows:

Reference Implementation
// Pivot on (N[x], B[y]).
void pivot(int x, int y) {
  std::swap(N[x], B[y]);
  long double v = -1 / tab[x][y];
  for (int j = 0; j <= m + 1; ++j) {
    tab[x][j] = j == y ? -v : v * tab[x][j];
  }
  for (int i = 0; i <= n; ++i) {
    if (i == x) continue;
    v = tab[i][y];
    tab[i][y] = 0;
    for (int j = 0; j <= m + 1; ++j) {
      tab[i][j] += v * tab[x][j];
    }
  }
}

This implementation shows that a single simplex-tableau update takes O(mn)O(mn) time. As discussed later in pivot rules, determining the leaving and entering variables also takes at most O(mn)O(mn) time, so a single pivot takes O(mn)O(mn) time.

For clarity, we list here the detailed steps for computing the example above using the condensed simplex tableau.

Example (continued)

Initially, the condensed simplex tableau is as follows:

x1x2x30−10−12−12x4=20122x5=20212x6=20221\begin{array}{|l|c|ccc|} \hline & & x_1 & x_2 & x_3 \\ \hline & 0 & -10 & -12 & -12 \\ \hline x_4= & 20 & 1 & 2 & 2 \\ x_5= & 20 & 2 & 1 & 2 \\ x_6= & 20 & 2 & 2 & 1 \\ \hline \end{array}

Based on the reduced costs in row 00, we can choose x1,x2,x3x_1,x_2,x_3 to enter. Let x1x_1 enter. The minimum ratio test then allows us to choose x5,x6x_5,x_6 to leave. Let x5x_5 leave. The updated condensed tableau is:

x5x2x31005−7−2x4=10−0.51.51x1=100.50.51x6=0−11−1\begin{array}{|l|c|ccc|} \hline & & x_5 & x_2 & x_3 \\ \hline &100 & 5 & -7 & -2 \\ \hline x_4= & 10 &-0.5 & 1.5 & 1 \\ x_1= & 10 & 0.5 & 0.5 & 1 \\ x_6= & 0 & -1 & 1 & -1 \\ \hline \end{array}

Based on the reduced costs in row 00, we can choose x2,x3x_2,x_3 to enter. Let x3x_3 enter. The minimum ratio test then allows us to choose x4,x1x_4,x_1 to leave. Let x4x_4 leave. The updated condensed tableau is:

x5x2x41204−42x3=10−0.51.51x1=01−1−1x6=10−1.52.51\begin{array}{|l|c|ccc|} \hline & & x_5 & x_2 & x_4 \\ \hline &120 & 4 & -4 & 2 \\ \hline x_3= & 10 &-0.5 & 1.5 & 1 \\ x_1= & 0 & 1 & -1 & -1 \\ x_6= & 10 & -1.5& 2.5 & 1 \\ \hline \end{array}

Based on the reduced costs in row 00, only x2x_2 can enter. Let x2x_2 enter. The minimum ratio test allows only x6x_6 to leave. Let x6x_6 leave. Using the elementary row operations above, the updated tableau is:

x5x4x61361.63.61.6x3=40.40.4−0.6x1=40.4−0.60.4x2=4−0.60.40.4\begin{array}{|l|c|ccc|} \hline & & x_5 & x_4 & x_6 \\ \hline &136 & 1.6 & 3.6 & 1.6 \\ \hline x_3= & 4 & 0.4 & 0.4 &-0.6 \\ x_1= & 4 & 0.4 & -0.6& 0.4 \\ x_2= & 4 & -0.6& 0.4 & 0.4 \\ \hline \end{array}

Since there is no entering variable according to the reduced costs in row 00, the current solution

x=(4,4,4,0,0,0)Tx=(4,4,4,0,0,0)^T

is optimal; the optimal value (for the minimization problem) is −136-136.

Besides implementing the simplex method with a simplex tableau, one can use the revised simplex method, which further improves the time and space complexity and reduces the complexity of one update to O(m2)O(m^2). It is especially efficient when m≪nm\ll n or AA is sparse.

Geometric Background

This section introduces the geometric background of the simplex method.

For the feasible region of the linear programming problem

D={x∈Rn:Ax=b, x≥0}\mathcal D = \{x\in\mathbf R^n : Ax = b,~ x\ge 0\}

the analysis shows that:

  • An optimal solution to a linear programming problem, if one exists, can always be chosen as a vertex of the feasible region D\mathcal D. Solving the linear programming problem therefore reduces to finding, among all vertex solutions, the one with the optimal value.
  • The coordinates of every vertex can be obtained by solving the system formed by nn tight constraints. For standard-form constraints, all mm equality constraints are necessarily tight, and the remaining n−mn-m constraints must be selected from the non-negativity constraints. Choosing these non-negativity constraints as tight constraints is equivalent to setting the corresponding decision variables xNx_N to 00. The system Ax=bAx = b then reduces, in the remaining mm decision variables xBx_B, to the linear system ABxB=bA_Bx_B = b. If ABA_B is invertible, we obtain xB=AB−1bx_B = A_B^{-1}b. This gives a solution (xB,xN)=(AB−1b,0)(x_B,x_N)=(A_B^{-1}b,0); if xB≥0x_B\ge 0, these are the coordinates of a vertex of D\mathcal D.

It is easy to see that the notion of a vertex solution agrees with the basic feasible solution defined above. Thus, finding the best basic feasible solution yields an optimal solution to the original problem. Although this greatly simplifies the problem, the number of vertices of the feasible region is exponential, so exhaustive search is impractical.

To overcome this difficulty, consider moving along an edge of the feasible region from one vertex to an adjacent vertex. Since adjacent vertices lie on the same edge, they satisfy at least n−1n-1 common tight constraints. In other words, the tight constraints corresponding to adjacent vertices differ in exactly one constraint. Therefore, for a basic feasible solution xx, replacing one basic variable with one non-basic variable yields an adjacent basic feasible solution x′x'. This is precisely a pivot.

Thus, the process in which the simplex method starts from a basic feasible solution and repeatedly pivots to improve the objective is exactly the process of starting at a vertex of the corresponding feasible region and moving to adjacent vertices to improve the objective.

Example (continued)

In the example discussed here, the feasible region is a three-dimensional polyhedron with five vertices, as shown below:

Figure: simplex geo

Geometrically, the solution process above corresponds to the following path between vertices of the polyhedron:

(0,0,0)→(0,0,10)→(10,0,0)→(4,4,4).(0,0,0) \rightarrow (0,0,10) \rightarrow (10,0,0) \rightarrow (4,4,4).

Implementation Details

The simplex tableau can solve many linear programming problems. However, for the most general cases, the simplex method still has many details worth examining.

Slack Form

The method for converting a linear programming problem in general form to standard form was discussed above. To make it convenient to solve with the simplex method, we also need the coefficient matrix AA to have full rank. Although converting to standard form and then removing linearly dependent constraints works, the following strategy is usually used for simplicity:

  1. Convert the linear programming problem to inequality form, namely min⁡{cTx:Ax≤b, x≥0}\min\{c^Tx : Ax \le b,~ x \ge 0\};
  2. Add slack variables ss to obtain standard form: min⁡{cTx:Ax+s=b, x≥0, s≥0}\min\{c^Tx : Ax + s = b,~ x\ge 0,~ s \ge 0\}.

The advantage is that the coefficient matrix (A,I)(A,I) of the resulting standard form is always full rank, and a (not necessarily feasible) basic solution (x,s)=(0,b)(x,s)=(0,b) always exists. This special standard form is called slack form.

Initial Basic Feasible Solution

The simplex method described above always assumes that a basic feasible solution is known. Sometimes one is easy to find. For example, if b≥0b\ge 0 in the slack form above, then (x,s)=(0,b)(x,s)=(0,b) is a basic feasible solution. This is the situation in the numerical example above.

For the general case, use the two-phase method. It performs the simplex method twice. The first phase solves a feasibility linear program and obtains a basic feasible solution of the original problem. The second phase starts from this basic feasible solution and applies the simplex method to solve the original problem.

Suppose the problem is in standard form min⁡{cTx:Ax=b≥0, x≥0}\min\{c^Tx : Ax = b \ge 0,~ x\ge 0\}. In the first phase, solve

min⁡{1Txa:Ax+xa=b, x≥0, s≥0}.\min\{1^Tx_a : Ax + x_a = b,~ x\ge 0,~ s\ge 0\}.

This is a feasibility linear program. The newly added variable xax_a is called an artificial variable. It has the basic feasible solution (x,xa)=(0,b)(x,x_a)=(0,b), so it can be solved directly by the simplex method. If the optimum is strictly greater than 00, then no x≥0x\ge 0 satisfies Ax=bAx=b, so the original problem is infeasible. If the optimum equals 00, the artificial variables in an optimal solution must all be zero. If some artificial variables are still basic, pivot them out through several pivots. Finally, when all artificial variables are non-basic, the basic solution obtained in phase one can be used as the initial basic feasible solution for phase two.

Phase One Without Explicit Artificial Variables

When implementing phase one, it is not necessary to introduce artificial variables explicitly. For any chosen initial basis BB, we have

xB+AB−1ANxN=AB−1b.x_B + A_B^{-1}A_Nx_N = A_B^{-1}b.

If (AB−1b)j≥0(A_B^{-1}b)_j\ge 0, no artificial variable is needed; otherwise, introduce an additional artificial variable xBj−x^{-}_{B_j}:

xBj−xBj−+(AB−1AN)(j)xN=(AB−1b)j.x_{B_j} - x^-_{B_j} + (A_B^{-1}A_N)_{(j)}x_N = (A_B^{-1}b)_j.

Let L:={j:(AB−1b)j<0}L:=\{j:(A_B^{-1}b)_j<0\}. Then the phase-one simplex tableaus are obtained from the following tableau by a sequence of elementary row operations:

xNxB∼LxBLxBL−00T0T0T1TxB∼L=(AB−1b)∼L(AB−1AN)(∼L)IOOxBL−=(AB−1b)L(AB−1AN)(L)OI−I\begin{array}{|r|c|cccc|} \hline & & x_N & x_{B_{\sim L}} & x_{B_L} &x_{B_{L}}^- \\ \hline & 0 & 0^T & 0^T & 0^T & 1^T \\ \hline x_{B_{\sim L}}= & (A_B^{-1}b)_{\sim L} & (A_B^{-1}A_N)_{(\sim L)} & I & O & O \\ x_{B_{L}}^-= & (A_B^{-1}b)_L & (A_B^{-1}A_N)_{(L)} & O & I & -I \\ \hline \end{array}

As with simplifying the simplex tableau to the condensed simplex tableau, it can be simplified appropriately (left-multiply the xBL−x_{B_{L}}^- row by 1T1^T, add it to row 00, and omit the last three columns):

xN1TbL1T(AB−1AN)LxB∼L=(AB−1b)∼L(AB−1AN)(∼L)−xBL=(AB−1b)L(AB−1AN)L\begin{array}{|r|c|cccc|} \hline & & x_N \\ \hline & 1^Tb_L & 1^T(A_B^{-1}A_N)_L \\ \hline x_{B_{\sim L}}= & (A_B^{-1}b)_{\sim L} & (A_B^{-1}A_N)_{(\sim L)} \\ -x_{B_{L}}= & (A_B^{-1}b)_L & (A_B^{-1}A_N)_L \\ \hline \end{array}

This is broadly the same as the ordinary condensed simplex tableau, except that the variable in the last row is marked with a minus sign, indicating that the row still contains an artificial variable and the original slack variable is still infeasible. Using this tableau, the pivoting process is as follows:

  1. If L=∅L=\varnothing, terminate.

  2. Otherwise, because the reduced cost in row 00 is negative, choose the entering variable xNix_{N_i}. If none exists, the original problem is infeasible; terminate.

  3. Using column ii, choose a leaving variable xBjx_{B_j}. Again use the minimum ratio test, but require both currently feasible variables to remain feasible and currently infeasible variables to remain infeasible; choose

    arg⁡min⁡j{(T~B)j0(T~B)ji:(j∉L∧(T~B)ji>0)∨(j∈L∧(T~B)ji<0)}\arg\min_{j}\left\{\dfrac{(\tilde T_B)_{j0}}{(\tilde T_B)_{ji}}:(j\notin L\land(\tilde T_B)_{ji}>0)\lor(j\in L\land(\tilde T_B)_{ji}<0)\right\}

    as the row containing the leaving variable. If several such leaving variables exist, prioritize an infeasible leaving variable.

  4. Let xNix_{N_i} enter and xBjx_{B_j} leave, then update the simplex tableau.

  5. If j∈Lj\in L, remove jj from LL (cancel the minus sign on that row) and add one to (T~B)0i(\tilde T_B)_{0i}.

The columns containing artificial variables can be omitted because if they are still basic, their columns are eje_j and need not be recorded; if they are no longer basic, they will never enter again and also need not be recorded. When an artificial variable leaves the basis, it must be replaced by the corresponding non-artificial variable, which is exactly the purpose of the final step above.

The reference implementation is as follows:

Reference Implementation
// First phase: find an initial BFS.
// Return false if no feasible solution.
bool initialize() {
  int neg_count = 0;
  for (int j = 0; j < m; ++j) {
    if (tab[n][j] < -eps) {
      for (int i = 0; i <= n; ++i) {
        tab[i][m + 1] += tab[i][j];
      }
      B[j] = ~B[j];
      ++neg_count;
    }
  }
  while (neg_count) {
    int x = -1;
    long double mi = -eps;
    for (int i = 0; i < n; ++i) {
      if (tab[i][m + 1] < mi) {
        x = i;
        mi = tab[i][m + 1];
      }
    }
    if (x == -1) return false;
    int y = -1;
    mi = INFINITY;
    for (int j = 0; j < m; ++j) {
      if ((B[j] < 0 && tab[x][j] < -eps) || (B[j] >= 0 && tab[x][j] > eps)) {
        auto tmp = tab[n][j] / tab[x][j] + (B[j] < 0 ? -eps : eps);
        if (tmp < mi) {
          y = j;
          mi = tmp;
        }
      }
    }
    if (B[y] < 0) {
      --neg_count;
      B[y] = ~B[y];
      pivot(x, y);
      tab[x][m + 1] += 1;
    } else {
      pivot(x, y);
    }
  }
  return true;
}

Before phase one starts, add an extra row to record the phase-one objective function. During pivoting, pivot the entire tableau, including the phase-two objective function. Thus, when phase one is complete, the phase-two objective has also been updated accordingly, and phase two can begin directly with the simplex method.

The two-phase method can also be implemented with a single simplex method. Choose a sufficiently large positive number MM and directly solve

min⁡{cTx+M1Txa:Ax+xa=b, x≥0, s≥0}\min\{c^Tx + M1^Tx_a : Ax + x_a = b,~ x\ge 0,~ s\ge 0\}

This yields the optimum of the original problem. In the implementation, MM is not assigned a concrete value; it is treated as an unknown sufficiently large positive number MM. This method is called the big MM method.

The Naive Algorithm Has Exponential Practical Complexity

Because the slack form always has an initial basic solution, though not necessarily a feasible one, a simple idea for finding an initial basic feasible solution is to start from an infeasible basic solution and repeatedly pivot out infeasible basic variables, choosing as the entering variable the non-basic variable in the column whose entry in the corresponding row is also negative, until all basic variables are nonnegative. The reference implementation is as follows:

Reference Implementation
// First phase: find an initial BFS.
// Return false if no feasible solution.
bool initialize() {
  while (true) {
    int y = -1;
    long double mi = -eps;
    for (int j = 0; j < m; ++j) {
      if (tab[n][j] <= mi) {
        y = j;
        mi = tab[n][j];
      }
    }
    // No row with a negative basic variable => Feasible.
    if (y == -1) break;
    int x = -1;
    for (int i = 0; i < n; ++i) {
      if (tab[i][y] < -eps && (x == -1 || N[i] > N[x])) {
        x = i;
      }
    }
    // No column with a negative entry => Infeasible.
    if (x == -1) return false;
    pivot(x, y);
  }
  return true;
}

Although this is simple, unlike the two-phase method it has no objective function describing how infeasible the current basis is, so it lacks a clear direction for improvement. In practice, compared with methods that usually need only O(m)O(m) pivots, namely the two-phase method or the big MM method, this naive algorithm usually needs O(2m)O(2^m) pivots and can easily enter cycles when n,mn,m are large. Although the constant factor in the number of pivots is small, the naive algorithm is only suitable for n,m<50n,m<50.

Pivot Rules

During pivoting, if there are multiple choices for entering or leaving variables, use a pivot rule to choose which variables enter or leave. With a simplex tableau, every rule discussed here can find the entering and leaving variables in O(mn)O(mn) time, so one pivot still takes O(mn)O(mn) time.

The choice of entering variable often determines the number of pivots before termination. Common rules include:

  • Choose the first entering variable found;
  • Choose the entering variable with the smallest label (part of Bland's rule);
  • Choose the entering variable with the largest absolute reduced cost (that is, ∣ci∣|c_i|; Dantzig's rule);
  • Choose the entering variable with the largest single-pivot improvement in the objective (that is, ∣ci∣θi|c_i|\theta_i);
  • Choose the entering variable corresponding to the steepest edge, namely the largest objective improvement per unit distance along the edge (that is, ∣ci∣/∥AB−1Ai∥|c_i|/\|A_B^{-1}A_i\|);
  • Choose an entering variable at random.

In practice, the steepest-edge rule is the most efficient2. It is generally believed that a suitable pivot rule finds an optimal solution for most problems in roughly 2m2m pivots. However, every currently known pivot rule has specially constructed examples3 that force the number of pivots to be exponential. This is why the simplex method performs quite well in practice but has exponential worst-case complexity in theory.

The choice of leaving variable often determines whether the algorithm enters a cycle. If several basic feasible solutions have the same optimal value, the algorithm may cycle among them indefinitely. Such cases are uncommon, so many simplex implementations do not specify a rule for choosing the leaving variable. Two common anti-cycling rules are:

  • Bland's rule: always choose the entering and leaving variables with the smallest labels.

  • Lexicographic rule: always choose a row with (AB−1Ai)j>0(A_B^{-1}A_i)_j>0 and

    ((AB−1b)j(AB−1Ai)j,(AB−1)j1(AB−1Ai)j,⋯ ,(AB−1)jm(AB−1Ai)j)\left(\dfrac{(A_B^{-1}b)_j}{(A_B^{-1}A_i)_j},\dfrac{(A_B^{-1})_{j1}}{(A_B^{-1}A_i)_j},\cdots,\dfrac{(A_B^{-1})_{jm}}{(A_B^{-1}A_i)_j}\right)

    the leaving variable corresponding to the lexicographically smallest row index jj, namely xBjx_{B_j}. The choice of entering variable is unimportant.

    If the linear programming problem is in slack form, all these quantities can be obtained directly from the tableau TBT_B described above. Otherwise, after finding an initial basic solution (not necessarily feasible), use the coefficients in the columns corresponding to the basic variables of this initial basis (with the order fixed) as the coefficients of AB−1A_B^{-1}.

Bland's rule is inefficient because it uses the same method to choose entering and leaving variables, which can easily cause the same variable to enter and leave repeatedly. The lexicographic rule is more practical. It is equivalent to perturbing the parameters of the linear programming problem4, so no two basic feasible solutions have the same optimal value and cycling is impossible.

Reference Implementation

This section provides a reference implementation of the two-phase simplex method based on the condensed simplex tableau.

Luogu P13337 [Template] Linear Programming
#include <algorithm>
#include <climits>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

// --8<-- [start:core]
int m, n;  // Number of constraints and variables.
std::vector<std::vector<long double>>
    tab;                             // Compressed tableau (transposed) with
                                     // first-phase objective attached.
std::vector<int> B, N;               // Basic and nonbasic variables.
constexpr long double eps = 1e-12l;  // Precision.

// --8<-- [start:pivot]
// Pivot on (N[x], B[y]).
void pivot(int x, int y) {
  std::swap(N[x], B[y]);
  long double v = -1 / tab[x][y];
  for (int j = 0; j <= m + 1; ++j) {
    tab[x][j] = j == y ? -v : v * tab[x][j];
  }
  for (int i = 0; i <= n; ++i) {
    if (i == x) continue;
    v = tab[i][y];
    tab[i][y] = 0;
    for (int j = 0; j <= m + 1; ++j) {
      tab[i][j] += v * tab[x][j];
    }
  }
}

// --8<-- [end:pivot]
// --8<-- [start:initialize]
// First phase: find an initial BFS.
// Return false if no feasible solution.
bool initialize() {
  int neg_count = 0;
  for (int j = 0; j < m; ++j) {
    if (tab[n][j] < -eps) {
      for (int i = 0; i <= n; ++i) {
        tab[i][m + 1] += tab[i][j];
      }
      B[j] = ~B[j];
      ++neg_count;
    }
  }
  while (neg_count) {
    int x = -1;
    long double mi = -eps;
    for (int i = 0; i < n; ++i) {
      if (tab[i][m + 1] < mi) {
        x = i;
        mi = tab[i][m + 1];
      }
    }
    if (x == -1) return false;
    int y = -1;
    mi = INFINITY;
    for (int j = 0; j < m; ++j) {
      if ((B[j] < 0 && tab[x][j] < -eps) || (B[j] >= 0 && tab[x][j] > eps)) {
        auto tmp = tab[n][j] / tab[x][j] + (B[j] < 0 ? -eps : eps);
        if (tmp < mi) {
          y = j;
          mi = tmp;
        }
      }
    }
    if (B[y] < 0) {
      --neg_count;
      B[y] = ~B[y];
      pivot(x, y);
      tab[x][m + 1] += 1;
    } else {
      pivot(x, y);
    }
  }
  return true;
}

// --8<-- [end:initialize]
// --8<-- [start:simplex]
// Second phase: find an optimal BFS.
// Return false if the problem is unbounded.
bool simplex() {
  while (true) {
    int x = -1;
    long double mi = -eps;
    for (int i = 0; i < n; ++i) {
      if (tab[i][m] < mi) {
        x = i;
        mi = tab[i][m];
      }
    }
    // No column with a negative reduced cost => Optimal.
    if (x == -1) break;
    int y = -1;
    mi = INFINITY;
    for (int j = 0; j < m; ++j) {
      if (tab[x][j] <= eps) continue;
      if (tab[n][j] / tab[x][j] < mi) {
        y = j;
        mi = tab[n][j] / tab[x][j];
      }
    }
    // No row with a positive ratio => Unbounded.
    if (y == -1) return false;
    pivot(x, y);
  }
  return true;
}

// --8<-- [end:simplex]
int solve() {
  B.resize(m);
  N.resize(n);
  std::iota(B.begin(), B.end(), n);
  std::iota(N.begin(), N.end(), 0);
  return initialize() ? (simplex() ? 0 : 1) : -1;
}

// --8<-- [end:core]
int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(nullptr);
  std::cout << std::fixed << std::setprecision(8);
  std::cin >> n >> m;
  tab.assign(n + 1, std::vector<long double>(m + 2));
  for (int i = 0; i < n; ++i) {
    std::cin >> tab[i][m];
    tab[i][m] = -tab[i][m];
  }
  for (int j = 0; j < m; ++j) {
    for (int i = 0; i <= n; ++i) {
      std::cin >> tab[i][j];
    }
  }
  switch (solve()) {
    case -1:
      std::cout << "Infeasible" << std::endl;
      break;
    case 1:
      std::cout << "Unbounded" << std::endl;
      break;
    case 0: {
      std::cout << tab[n][m] << std::endl;
      std::vector<long double> x(n);
      for (int j = 0; j < m; ++j) {
        if (B[j] < n) x[B[j]] = tab[n][j];
      }
      for (int i = 0; i < n; ++i) {
        std::cout << x[i] << ' ';
      }
      std::cout << std::endl;
      break;
    }
  }
  return 0;
}

Examples

「NOI2008」

nn ,Here,the ii bib_i . mm ,Here,the jj canofis [lj,rj][l_j,r_j],withis cic_i.of,such thatof.

Note

letthe jj xjx_j .,canis

max⁡x  ∑j=1mcjxjsubject to ∑i=1naijxj≥bi, i=1,⋯ ,n,xj≥0, j=1,⋯ ,m.\begin{align*} \max_{x}\; & \sum_{j=1}^mc_jx_j \\ \text{subject to }& \sum_{i=1}^n a_{ij}x_j \ge b_i,~i=1,\cdots,n,\\ & x_j\ge 0,~j=1,\cdots,m. \end{align*}

Here,

aij={1,lj≤i≤rj,0,otherwise.a_{ij} = \begin{cases} 1,& l_j\le i\le r_j,\\ 0,& \text{otherwise.} \end{cases}

Clearlyofrow.Therefore,Consider for:

min⁡y  ∑i=1nbiyisubject to ∑j=1naijyi≤cj, j=1,⋯ ,m,yi≥0, i=1,⋯ ,n.\begin{align*} \min_{y}\; & \sum_{i=1}^n b_iy_i \\ \text{subject to } & \sum_{j=1}^na_{ij}y_i \le c_j,~j=1,\cdots,m,\\ & y_i\ge 0,~i=1,\cdots,n. \end{align*}

,obtainrow,can,.for,obtainofisof.

#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
constexpr int M = 10005, N = 1005, INF = 1e9;

int n, m;
double a[M][N], b[M], c[N], v;

void pivot(int l, int e) {  // function
  b[l] /= a[l][e];
  for (int j = 1; j <= n; j++)
    if (j != e) a[l][j] /= a[l][e];
  a[l][e] = 1 / a[l][e];

  for (int i = 1; i <= m; i++)
    if (i != l && fabs(a[i][e]) > 0) {
      b[i] -= a[i][e] * b[l];
      for (int j = 1; j <= n; j++)
        if (j != e) a[i][j] -= a[i][e] * a[l][j];
      a[i][e] = -a[i][e] * a[l][e];
    }

  v += c[e] * b[l];
  for (int j = 1; j <= n; j++)
    if (j != e) c[j] -= c[e] * a[l][j];
  c[e] = -c[e] * a[l][e];

  // swap(B[l],N[e])
}

double simplex() {
  while (true) {
    int e = 0, l = 0;
    for (e = 1; e <= n; e++)
      if (c[e] > (double)0) break;
    if (e == n + 1) return v;  // whenvnamelyis
    double mn = INF;
    for (int i = 1; i <= m; i++) {
      if (a[i][e] > (double)0 && mn > b[i] / a[i][e]) {
        mn = b[i] / a[i][e];  // fortheseeofl
        l = i;
      }
    }
    if (mn == INF) return INF;  // unbounded
    pivot(l, e);                // l,e
  }
}

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> c[i];
  for (int i = 1; i <= m; i++) {
    int s, t;
    cin >> s >> t;
    for (int j = s; j <= t; j++) a[i][j] = 1;  // denotestheikindsinjwhencan
    cin >> b[i];
  }
  cout << (int)(simplex() + 0.5);
}

Exercises

References

  • 【 + 】
  • 2016
  • algorithm
  • Matoušek, Jiří, and Bernd Gärtner. Understanding and using linear programming. Vol. 1. Berlin: Springer, 2007.
  • Inayatullah, Syed, Nasir Touheed, and Muhammad Imtiaz. "A streamlined artificial variable free version of simplex method." PloS one 10, no. 3 (2015): e0116156.
  • Floudas, Christodoulos A., and Panos M. Pardalos, eds. Encyclopedia of optimization. Springer Science & Business Media, 2008.

Footnotes

  1. then,for allvectoriscolumn vector,(xB,xN)(x_B,x_N) (xBT,xNT)T(x_B^T,x_N^T)^T.howeveris,of (xB,xN)(x_B,x_N),. ↩

  2. see Forrest, John J., and Donald Goldfarb. "Steepest-edge simplex algorithms for linear programming." Mathematical programming 57, no. 1 (1992): 341-374. ↩

  3. ofcansee Klee, Victor, and George J. Minty. "How good is the simplex algorithm." Inequalities 3, no. 3 (1972): 159-175. ↩

  4. ofcan these. ↩

This content comes from OI Wiki: Simplex Method. See the original for authors and revision history. AIOJ has adapted the formatting, in-site links, and resource paths.

Content is shared under CC BY-SA 4.0 and SATA license; additional terms are governed by the original notice. Thanks to the OI Wiki authors and contributors; per the SATA terms, please visit the OI Wiki repository and star it to show your support.