Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Appendix: Integer Pivoting

Motivating Example: Two Views of a Polytope

Consider the following set of points:

P={i=14λivi  |  i=14λi=1λi0for all ivi{(0,0),(1/3,0),(1/4,1/4),(0,1/3)}}\mathcal{P} = \left\{ \sum_{i=1}^{4} \lambda_i v_i\;\middle|\; \begin{array}{l} \sum_{i=1}^4 \lambda_i = 1 \\ \lambda_i \geq 0 \quad \text{for all } i \\ v_i \in \{(0, 0), (1/3, 0), (1/4, 1/4), (0, 1/3)\} \end{array} \right\}

This set P\mathcal{P} is a polytope, defined as the convex hull of a finite set of vertices:

V={(0,0), (1/3,0), (1/4,1/4), (0,1/3)}.V = \{(0, 0),\ (1/3, 0),\ (1/4, 1/4),\ (0, 1/3)\}.

A visualization is provided in Figure A5.1.

A 2D polytope shown as a convex hull

Figure A5.1:The two-dimensional polytope defined by (A5.1), shown as the convex hull of four points.

Polytopes can also be equivalently defined as the intersection of half- spaces, that is, bounded regions formed by linear inequalities. This alternate view is illustrated in Figure A5.2.

A 2D polytope as an intersection of half-spaces

Figure A5.2:The same polytope shown in Figure A5.1, represented as the intersection of linear inequalities.

This second definition corresponds to:

P={xR2  |  x10x20x1+3x213x1+x21}\mathcal{P} = \left\{ x \in \mathbb{R}^2\;\middle|\; \begin{array}{l} x_1 \geq 0 \\ x_2 \geq 0 \\ x_1 + 3x_2 \leq 1 \\ 3x_1 + x_2 \leq 1 \\ \end{array} \right\}

The inequalities in (A5.3) define supporting half-spaces that together enclose the polytope.

Polytopes appear throughout mathematics, particularly in optimisation, where they form the feasible regions of linear programs. These connections are central to game theory, especially in the study of zero-sum games and general games.

While this example lives in R2\mathbb{R}^2, the techniques extend to higher-dimensional polytopes. The goal of this chapter is to develop tools for moving from vertex to vertex in such polytopes, an essential idea in both mathematical optimisation and algorithmic game theory.

Theory

Definition: Polytope as a Convex Hull

Let VRKV \subseteq \mathbb{R}^K be a finite set of points. A polytope P\mathcal{P} is the set of all convex combinations of points in VV:

P={i=1VλiviRK  |  i=1Vλi=1,  λi0,  viV}\mathcal{P} = \left\{ \sum_{i=1}^{|V|} \lambda_i v_i \in \mathbb{R}^K \;\middle|\; \sum_{i=1}^{|V|} \lambda_i = 1,\; \lambda_i \geq 0,\; v_i \in V \right\}

Definition: Polytope as an Intersection of Half-Spaces

Let MRm×nM \in \mathbb{R}^{m \times n} and bRmb \in \mathbb{R}^m. A polytope P\mathcal{P} can also be defined as the set of points satisfying a system of linear inequalities:

P={xRn  |  Mxb}\mathcal{P} = \left\{ x \in \mathbb{R}^n \;\middle|\; Mx \leq b \right\}

The representation of a polytope as the intersection of half-spaces via MxbMx \leq b will allow us to work efficiently with large systems.

Definition: Slack Variable

Given a system of linear inequalities of the form MxbMx \leq b, a slack variable transforms each inequality into an equality by accounting for the difference between the left- and right-hand sides.

Formally, for each row ii, the inequality

(Mx)ibi(Mx)_i \leq b_i

can be rewritten as

(Mx)i+si=biwithsi0,(Mx)_i + s_i = b_i \quad \text{with} \quad s_i \geq 0,

where si0s_i\geq 0 is the slack variable corresponding to the ii-th inequality.

Definition: Tableau Representation of Vertices

For MRm×nM \in \mathbb{R}^{m \times n} and bRmb \in \mathbb{R}^m, given a system of linear inequalities:

MxbMx \leq b

This system of linear inequalities can be written as a system of equalities by adding slack variables to give a modified linear system of equalities:

Mˉxˉ=b\bar M \bar x = b

Where MˉRm×m+n\bar M \in\mathbb{R}^{m \times m + n} and xˉRm+1\bar x \in \mathbb{R} ^{m + 1} includes coefficients for the added slack variables:

Mˉ=(MIm)xˉ=(x1xns1sm)\bar M = \begin{pmatrix} M & I_{m} \end{pmatrix} \qquad \bar x = \begin{pmatrix}x_1\\ \vdots \\ x_n \\ s_1 \\ \vdots \\ s_m\end{pmatrix}

Given the system Mˉxˉ=b\bar M \bar x = b a tableau is an extended matrix of the form:

(MˉImb)\begin{pmatrix}\bar M & I_m & b\end{pmatrix}

This augmented matrix of the underlying linear system is used to represent points in Polytopes. Through elementary row operations which will be called pivots we can move from one vertex to another.

Example: Tableaux for the Motivating Example

The linear system for the Motivating Example is:

x1+3x213x1+x21\begin{align*} x_1 + 3x_2&\leq 1 \\ 3x_1 + x_2 &\leq 1 \end{align*}

This corresponds to:

M=(1331)b=(11)M = \begin{pmatrix} 1 & 3\\ 3 & 1\\ \end{pmatrix} \qquad b = \begin{pmatrix} 1\\ 1\\ \end{pmatrix}

We can write a Tableau that represents the equivalent system of equations Mˉxˉ=b\bar M \bar x = b:

T(1)=(1310131011)T^{(1)} = \begin{pmatrix} 1 & 3 & 1 & 0 & 1\\ 3 & 1 & 0 & 1 & 1 \end{pmatrix}

Tableaux are augmented matrices for linear systems, it is possible to do elementary row operations on them that do not modify the underlying system. We can also derive alternative tableaux from this example:

Multiplying T(1)T^{(1)}'s row 1 by 3 and subtracting row 2 gives:

T(2)=(0831231011)T^{(2)} = \begin{pmatrix} 0 & 8 & 3 & -1 & 2\\ 3 & 1 & 0 & 1 & 1 \end{pmatrix}

Multiplying T(2)T^{(2)}'s row 2 by 8 and subtracting row 1 gives:

T(3)=(08312240396)T^{(3)} = \begin{pmatrix} 0 & 8 & 3 & -1 & 2\\ 24 & 0 & -3 & 9 & 6 \end{pmatrix}

Multiplying T(3)T^{(3)}'s row 1 by 9 and adding row 2 gives:

T(4)=(247224024240396)T^{(4)} = \begin{pmatrix} 24 & 72 & 24 & 0 & 24\\ 24 & 0 & -3 & 9 & 6 \end{pmatrix}

There are other tableaux that correspond to the same systems of equations but we next explore how tableaux correspond to vertices of polytopes. To do this we need a new definition:

Definition: Basic variables


A basic variable of a tableau corresponds to a column that is linearly independent from the others.


Example: Basic variables for the different Tableaux of the Motivating Example

The basic variables for:

Thus, the non-basic variables for:

Equivalence between a tableau and a vertex

A tableau represents the constraints and feasible region of a polytope. A given tableau represents a vertex of the polytope.

To obtain a vertex from the tableau:

Example: equivalence between tableaux and vertices

  1. For (A5.14): we set the non-basic variables to 0:

    x1=0x2=0x_1=0\qquad x_2=0

    The remaining linear system from the tableau is:

    s1=1s2=1\begin{align*} s_1=1\\ s_2=1 \end{align*}

    Note that we do not need to solve this remaining linear system as setting the non-basic variables to 0 immediately gives us the vertex: (x1,x2)=(0,0)(x_1, x_2)=(0, 0) (the origin of Figure A5.1).

  2. For (A5.15): we set the non-basic variables to 0:

    x2=0s2=0x_2=0\qquad s_2=0

    The remaining linear system from the tableau is:

    3x1=13s1=2\begin{align*} 3x_1=1\\ 3s_1=2 \end{align*}

    Solving this gives: (x1,x2)=(1/3,0)(x_1, x_2)=(1/3, 0) (the bottom right vertex of Figure A5.1).

  3. For (A5.16): we set the non-basic variables to 0:

    s1=0s2=0s_1=0\qquad s_2=0

    The remaining linear system from the tableau is:

    24x1=68x2=2\begin{align*} 24x_1=6\\ 8x_2=2 \end{align*}

    Solving this gives: (x1,x2)=(1/4,1/4)(x_1, x_2)=(1/4, 1/4) (the top right vertex of Figure A5.1).

  4. For (A5.17): we set the non-basic variables to 0:

    x1=0s1=0x_1=0\qquad s_1=0

    The remaining linear system from the tableau is:

    72x2=249s2=6\begin{align*} 72x_2=24\\ 9s_2=6 \end{align*}

    Solving this gives: (x1,x2)=(0,1/3)(x_1, x_2)=(0, 1/3) (the top left vertex of Figure A5.1).

We have recovered all four vertices from the 4 tableaux of Example: Tableaux for the Motivating Example. Note that in that example through the process of applying elementary row operations to the tableaux we moved across the edges of the polytope as shown in Figure A5.3.

The same 2D polytope with arrows showing movement across edges.

Figure A5.3:The two-dimensional polytope defined by (A5.1), with arrows showing the process of moving along the edges. The various row operations are written as short hand.

This process corresponds to making a non-basic variable basic and carefully choosing which basic variable to make non-basic.

Definition: Integer Pivoting

Pivoting is the process of updating a tableau by selecting one basic variable to leave the basis and one non-basic variable to enter it. This corresponds to performing row operations to rewrite the system so that the new basic variable appears with coefficient 1 in its row and 0 in all others.

In integer pivoting, we perform this process using only integer-preserving row operations, such as adding or subtracting integer multiples of rows. This is useful for maintaining exact arithmetic and geometric intuition in discrete settings.

Suppose you are given a tableau representing a system of equations and you choose a non-basic variable xjx_j to enter the basis.

The goal is to perform a pivot so that xjx_j becomes basic and one of the current basic variables is removed from the basis.

The pivot is carried out using the following steps:

  1. Identify the pivot column Select the column of the tableau corresponding to xjx_j.

  2. Select the pivot row minimum ratio test For each row ii where the coefficient Tij>0T_{ij} > 0, compute the ratio:

    biTij\frac{b_i}{T_{ij}}

    (where bib_i corresponds to the final column of TT.)

    Choose the row rr with the smallest non-negative ratio. The basic variable in this row will leave the basis.

  3. Eliminate the pivot column in all other rows For each row iri \neq r, if necessary multiply it by a suitable integer multiplier and then subtract suitable integer multiples of row rr so that the entry in column jj becomes zero.

After these steps, the tableau reflects a new basic solution where xjx_j is basic, and one previous basic variable has become non-basic.

Example: Moving from T(1)T^{(1)} to T(2)T^{(2)}

Let us start at:

T(1)=(1310131011)T^{(1)} = \begin{pmatrix} 1 & 3 & 1 & 0 & 1\\ 3 & 1 & 0 & 1 & 1 \end{pmatrix}

The non-basic variables are x1x_1 and x2x_2. Let us choose to let x2x_2 become basic. This corresponds to the second column of the tableau.

Next we use the minimum ratio test:

  1. The ratio for the first row: 13\frac{1}{3}

  2. The ratio for the second row: 11\frac{1}{1}

Both of these are non-negative and the minimum value is obtained in the first row. Thus we pivot on the first row making the value in the second column and “all other rows” (in this case just the second row) 0.

Multiplying T(1)T^{(1)}'s row 2 by 3 and subtracting row 1 gives:

T(2)=(1310180132)T^{(2)} = \begin{pmatrix} 1 & 3 & 1 & 0 & 1\\ 8 & 0 & -1 & 3 & 2 \end{pmatrix}

Using Equivalence between a tableau and a vertex we set the basic variables to 0:

x1=0s1=0x_1=0\qquad s_1=0

The remaining linear system from the tableau is:

3x2=13s2=2\begin{align*} 3x_2=1\\ 3s_2=2 \end{align*}

Solving this gives: (x1,x2)=(0,1/3)(x_1, x_2)=(0, 1/3).

Exercises

Exercise: Polytope Representation

For each of the following sets of vertices:

  1. V={(0,0),(0,1),(1,0),(1,1)} V = \{(0, 0), (0, 1), (1, 0), (1, 1)\}

  2. V={(0,0),(0,14),(1,23),(2,15)} V = \{(0, 0), (0, \tfrac{1}{4}), (1, \tfrac{2}{3}), (2, \tfrac{1}{5})\}

  3. V={(0,0),(0,14),(1,23),(2,15),(1,0)} V = \{(0, 0), (0, \tfrac{1}{4}), (1, \tfrac{2}{3}), (2, \tfrac{1}{5}), (1, 0)\}


Exercise: Basic and Non-Basic Variables

For each of the following tableaux, identify the basic and non-basic variables:

  1. T(a)=(1051101491)T^{(a)} = \begin{pmatrix} 1 & 0 & 5 & 1 & 1\\ 0 & 1 & 4 & 9 & 1 \end{pmatrix}
  2. T(b)=(4810181011)T^{(b)} = \begin{pmatrix} 4 & 8 & 1 & 0 & 1\\ 8 & 1 & 0 & 1 & 1 \end{pmatrix}

Exercise: Integer Pivoting

For the tableaux in Exercise: Basic and Non-Basic Variables:

For each non-basic variable, perform one step of integer pivoting:

  1. Identify the pivot column;

  2. Perform the minimum ratio test to determine the pivot row;

  3. Execute the required row operations to complete the pivot.

Programming

Using SciPy to obtain the convex hull

The SciPy library has functionality to obtain the convex hull of a set of vertices.

import scipy.spatial
import numpy as np

V = [np.array([0, 0]), np.array([1 / 3, 0]), np.array([1 / 4, 1 / 4]),
np.array([0, 1 / 3])]
P = scipy.spatial.ConvexHull(V)
scipy.spatial.convex_hull_plot_2d(P);
<Figure size 640x480 with 1 Axes>

The obtained convex hull can be used to get the system of linear inequalities:

P.equations
array([[-0. , -1. , 0. ], [-1. , 0. , -0. ], [ 0.9486833 , 0.31622777, -0.31622777], [ 0.31622777, 0.9486833 , -0.31622777]])

Using SciPy to obtain the half space

The Scipy library has functionality to obtain the vertices from a given intersection of half spaces.

First we create the system of linear inequalities MxbMx \leq b, this is done passing: (M,b)(M, -b) as single matrix

halfspace = np.array(
    (
        (-1, 0, 0),
        (0, -1, 0),
        (3, 1, -1),
        (1, 3, -1),
    )
)

We need to pass a point known to be in the interior of the Polytope. Now we can obtain the vertices the original vertices from (A5.1).

P = scipy.spatial.HalfspaceIntersection(halfspace, interior_point=np.array((1/5,
1/5)))
P.intersections
array([[2.77555756e-17, 3.33333333e-01], [2.50000000e-01, 2.50000000e-01], [0.00000000e+00, 0.00000000e+00], [3.33333333e-01, 2.77555756e-17]])

Carrying out row operations using NumPy

NumPy’s array operations allow for straightforward row operations.

T_1 = np.array(
    (
        (1, 3, 1, 0, 1),
        (3, 1, 0, 1, 1),
    )
)
T_2 = T_1
T_2[0] = 3 * T_2[0] - T_2[1]
T_2
array([[ 0, 8, 3, -1, 2], [ 3, 1, 0, 1, 1]])

Pivoting tableaux with Nashpy

NashPy has some internal functionality for integer pivoting, which at present is not designed to be user facing but is nonetheless useable:

import nashpy as nash

T = nash.linalg.Tableau(T_2)

Having created this tableau we can get the indices of the basic and non-basic variables:

T.basic_variables
{0, 2}
T.non_basic_variables
{np.int64(1), np.int64(3)}

We can pivot the tableau on a given column and given row:

T._pivot(column_index=1, pivot_row_index=1)

This pivoted on the second column (index 1) returning which non-basic variable becomes basic as a result.

We can look at the tableau:

T._tableau
array([[-24, 0, 3, -9, -6], [ 3, 1, 0, 1, 1]])

Notable Research

The concept of pivoting and tableaux was first introduced by the mathematician George Dantzig in a 1947 report during his tenure at the Pentagon Dantzig, 1947.

The initial publication of this idea is found in Dantzig, 1951. Although Dantzig did not explicitly mention tableaux, they naturally emerged as an efficient method for traversing the edges of a polytope.

In Dantzig, 2020 (originally published in 1990), Dantzig shares the following anecdote:

"The first idea that would occur to anyone as a technique for solving a linear program, aside from the obvious one of moving through the interior of the convex set, is that of moving from one vertex to the next along the edges of the polyhedral set. I discarded this idea immediately as impractical in higher dimensional spaces. It seemed intuitively obvious that there would be far too many vertices and edges to wander over in the general case for such a method to be efficient.

When Hurwicz came to visit me at the Pentagon in the summer of 1947, I told him how I had discarded this vertex-edge approach as intuitively inefficient for solving LP. I suggested instead that we study the problem in the geometry of columns rather than the usual one of the rows -- column geometry incidentally was the one I had used in my Ph.D. thesis on the Neyman-Pearson Lemma. We dubbed the new method ‘climbing the bean pole.’"

A comprehensive historical overview is provided in Todd, 2002, which includes several other notable publications.

Two significant works connect integer pivoting to game theory:

Conclusion

Integer pivoting offers a powerful lens through which to understand movement across the vertices of polytopes, providing a concrete foundation for key algorithms in linear programming and game theory. Through the tableau representation, we are able to:

These tools underpin the algorithms used for zero-sum games and Nash equilibrium computation.

Table A5.1 summarises the key concepts introduced in this appendix.

Table A5.1:Summary of integer pivoting

ConceptDescription
Polytope (convex hull)Set of convex combinations of finite points
Polytope (half-spaces)Set of solutions to a system of linear inequalities
Slack variableConverts an inequality into an equality with a non-negative remainder
TableauAugmented matrix form of a linear system with slack variables
Basic variableVariable corresponding to a pivot column; used to determine a vertex
Non-basic variableSet to 0 when solving for vertex from tableau
PivotingRow operations used to exchange basic and non-basic variables
Minimum ratio testSelects the pivot row to preserve feasibility during a pivot
Integer pivotingPivoting using only integer row operations to maintain exact structure

Solutions

Solution to Exercise: Polytope Representation

1. V={(0,0),(0,1),(1,0),(1,1)}V = \{(0,0), (0,1), (1,0), (1,1)\}

This is the unit square. As the intersection of half-spaces:

P={xR2x10, x20, x11, x21}\mathcal{P} = \{x \in \mathbb{R}^2 \mid x_1 \geq 0,\ x_2 \geq 0,\ x_1 \leq 1,\ x_2 \leq 1\}

In standard form MxbMx \leq b:

M=(10011001),b=(0011).M = \begin{pmatrix}-1 & 0 \\ 0 & -1 \\ 1 & 0 \\ 0 & 1\end{pmatrix}, \qquad b = \begin{pmatrix}0 \\ 0 \\ 1 \\ 1\end{pmatrix}.

2. V={(0,0),(0,1/4),(1,2/3),(2,1/5)}V = \{(0,0), (0, 1/4), (1, 2/3), (2, 1/5)\}

We must find the convex hull of these four points. Computing the supporting half-spaces (using the convex hull):

The edges of the convex hull connect:

A complete half-space representation is:

x10,x110x20,5x1+12x23,7x1+15x217,x12.x_1 \geq 0, \quad x_1 - 10 x_2 \leq 0, \quad -5x_1 + 12x_2 \leq 3, \quad 7x_1 + 15x_2 \leq 17, \quad x_1 \leq 2.
import scipy.spatial
import numpy as np
import matplotlib.pyplot as plt

V1 = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float)
hull1 = scipy.spatial.ConvexHull(V1)
fig, axes = plt.subplots(1, 3, figsize=(9, 3))

for ax, V, title in zip(
    axes,
    [
        np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float),
        np.array([[0,0],[0,1/4],[1,2/3],[2,1/5]], dtype=float),
        np.array([[0,0],[0,1/4],[1,2/3],[2,1/5],[1,0]], dtype=float),
    ],
    ["V1: unit square", "V2: 4 points", "V3: 5 points"]
):
    hull = scipy.spatial.ConvexHull(V)
    scipy.spatial.convex_hull_plot_2d(hull, ax=ax)
    ax.scatter(V[:, 0], V[:, 1], color="red", zorder=5)
    ax.set_title(title)

plt.tight_layout()
<Figure size 900x300 with 3 Axes>
# Show the half-space inequalities for V2
V2 = np.array([[0,0],[0,1/4],[1,2/3],[2,1/5]], dtype=float)
hull2 = scipy.spatial.ConvexHull(V2)
print("Half-space equations for V2 (each row: [a, b, c] means a*x1 + b*x2 + c <= 0):")
print(hull2.equations)
Half-space equations for V2 (each row: [a, b, c] means a*x1 + b*x2 + c <= 0):
[[ 0.09950372 -0.99503719 -0.        ]
 [ 0.42288547  0.90618314 -1.02700756]
 [-1.          0.         -0.        ]
 [-0.38461538  0.92307692 -0.23076923]]

3. V={(0,0),(0,1/4),(1,2/3),(2,1/5),(1,0)}V = \{(0,0), (0,1/4), (1,2/3), (2,1/5), (1,0)\}

The point (1,0)(1,0) lies inside or on the boundary of the convex hull of VV from part 2 (it is below the bottom edge x110x20x_1 - 10x_2 \leq 0 at x1=1x_1=1: 10=1>01 - 0 = 1 > 0, so (1,0)(1,0) is actually outside that edge). Adding (1,0)(1,0) changes the convex hull.

V3 = np.array([[0,0],[0,1/4],[1,2/3],[2,1/5],[1,0]], dtype=float)
hull3 = scipy.spatial.ConvexHull(V3)
print("Half-space equations for V3:")
print(hull3.equations)
print("\nVertices of hull3:", V3[hull3.vertices])
Half-space equations for V3:
[[ 0.42288547  0.90618314 -1.02700756]
 [-1.          0.         -0.        ]
 [-0.38461538  0.92307692 -0.23076923]
 [-0.         -1.          0.        ]
 [ 0.19611614 -0.98058068 -0.19611614]]

Vertices of hull3: [[2.         0.2       ]
 [1.         0.66666667]
 [0.         0.25      ]
 [0.         0.        ]
 [1.         0.        ]]

Solution to Exercise: Basic and Non-Basic Variables

1. For

T(a)=(1051101491)T^{(a)} = \begin{pmatrix} 1 & 0 & 5 & 1 & 1 \\ 0 & 1 & 4 & 9 & 1 \end{pmatrix}

The columns (from left to right) correspond to variables x1,x2,x3,x4x_1, x_2, x_3, x_4 (or s1,s2s_1, s_2 if these are slack variables). A basic variable corresponds to a column that has exactly one nonzero entry (a unit vector). Inspecting the columns:

Basic variables: x1,x2x_1, x_2. Non-basic variables: x3,x4x_3, x_4.

Setting non-basic variables to zero: x3=x4=0x_3 = x_4 = 0, the system gives x1=1x_1 = 1 and x2=1x_2 = 1, so the corresponding vertex is (x1,x2)=(1,1)(x_1, x_2) = (1, 1) (if x3,x4x_3, x_4 are the original variables, otherwise the vertex is in the x1,x2x_1, x_2 coordinates).

2. For

T(b)=(4810181011)T^{(b)} = \begin{pmatrix} 4 & 8 & 1 & 0 & 1 \\ 8 & 1 & 0 & 1 & 1 \end{pmatrix}

Basic variables: s1,s2s_1, s_2. Non-basic variables: x1,x2x_1, x_2.

Setting non-basic variables to zero: x1=x2=0x_1 = x_2 = 0, and from the last column, s1=1s_1 = 1, s2=1s_2 = 1. This corresponds to the origin vertex.


Solution to Exercise: Integer Pivoting

We perform integer pivoting on each non-basic variable for the two tableaux from the exercise above.

Pivoting on T(a)T^{(a)}: The non-basic variables are x3x_3 and x4x_4.

Pivot on x3x_3 (column 3):

The pivot column entries are (5,4)(5, 4). Both are positive, so we apply the minimum ratio test:

The minimum ratio is 1/51/5 in row 1, so we pivot on row 1.

To eliminate x3x_3 from row 2 by integer pivoting (as defined in Definition: Integer Pivoting), multiply row 2 by 5 and subtract 4 times row 1, zeroing out column 3 in row 2:

new row 2=5×(0,1,4,9,1)4×(1,0,5,1,1)=(0,5,20,45,5)(4,0,20,4,4)=(4,5,0,41,1).\begin{align*} \text{new row 2} &= 5 \times (0,1,4,9,1) - 4 \times (1,0,5,1,1) \\ &= (0,5,20,45,5) - (4,0,20,4,4) = (-4, 5, 0, 41, 1). \end{align*}

The updated tableau is:

T(a)=(10511450411)T^{(a')} = \begin{pmatrix} 1 & 0 & 5 & 1 & 1 \\ -4 & 5 & 0 & 41 & 1 \end{pmatrix}

The basic variables are now x3x_3 (from row 1) and x2x_2 (from row 2). Setting non-basic variables x1=x4=0x_1 = x_4 = 0: from row 1, 5x3=1x3=1/55x_3 = 1 \Rightarrow x_3 = 1/5; from row 2, 5x2=1x2=1/55x_2 = 1 \Rightarrow x_2 = 1/5.

Pivot on x4x_4 (column 4) of T(a)T^{(a)}:

The pivot column entries are (1,9)(1, 9). Both positive. Minimum ratio test:

Minimum is 1/91/9 in row 2. Pivot on row 2. Eliminate x4x_4 from row 1: multiply row 1 by 9 and subtract row 2 (integer pivoting):

new row 1=9×(1,0,5,1,1)1×(0,1,4,9,1)=(9,0,45,9,9)(0,1,4,9,1)=(9,1,41,0,8).\begin{align*} \text{new row 1} &= 9 \times (1,0,5,1,1) - 1 \times (0,1,4,9,1) \\ &= (9,0,45,9,9) - (0,1,4,9,1) = (9, -1, 41, 0, 8). \end{align*}

The updated tableau is:

T(a)=(91410801491)T^{(a'')} = \begin{pmatrix} 9 & -1 & 41 & 0 & 8 \\ 0 & 1 & 4 & 9 & 1 \end{pmatrix}

Pivoting on T(b)T^{(b)}: The non-basic variables are x1x_1 and x2x_2.

Pivot on x1x_1 (column 1):

The pivot column entries are (4,8)(4, 8). Both positive. Minimum ratio test:

Minimum is 1/81/8 in row 2. Pivot on row 2. Eliminate x1x_1 from row 1:

new row 1=8×(4,8,1,0,1)4×(8,1,0,1,1)=(32,64,8,0,8)(32,4,0,4,4)=(0,60,8,4,4).\begin{align*} \text{new row 1} &= 8 \times (4,8,1,0,1) - 4 \times (8,1,0,1,1) \\ &= (32,64,8,0,8) - (32,4,0,4,4) = (0, 60, 8, -4, 4). \end{align*}

The updated tableau is:

T(b)=(06084481011)T^{(b')} = \begin{pmatrix} 0 & 60 & 8 & -4 & 4 \\ 8 & 1 & 0 & 1 & 1 \end{pmatrix}

Basic variables are now x1x_1 (row 2) and s1s_1 (row 1). Setting x2=s2=0x_2 = s_2 = 0: from row 2, 8x1=1x1=1/88x_1 = 1 \Rightarrow x_1 = 1/8.

Pivot on x2x_2 (column 2):

Starting from T(b)T^{(b)}, the pivot column entries are (8,1)(8, 1). Both positive. Minimum ratio test:

Minimum is 1/81/8 in row 1. Pivot on row 1. Eliminate x2x_2 from row 2:

new row 2=8×(8,1,0,1,1)1×(4,8,1,0,1)=(64,8,0,8,8)(4,8,1,0,1)=(60,0,1,8,7).\begin{align*} \text{new row 2} &= 8 \times (8,1,0,1,1) - 1 \times (4,8,1,0,1) \\ &= (64,8,0,8,8) - (4,8,1,0,1) = (60, 0, -1, 8, 7). \end{align*}

The updated tableau is:

T(b)=(48101600187)T^{(b'')} = \begin{pmatrix} 4 & 8 & 1 & 0 & 1 \\ 60 & 0 & -1 & 8 & 7 \end{pmatrix}

Basic variables are now s1s_1 (row 1) and x2x_2 (row 2). Setting x1=s2=0x_1 = s_2 = 0: from row 1, 8x2+s1=18x_2 + s_1 = 1; from row 2, 8s2=78s_2 = 7... Actually with x1=s2=0x_1 = s_2 = 0: row 1 gives 8x2=1x2=1/88x_2 = 1 \Rightarrow x_2 = 1/8.

import numpy as np

# Tableau T^(a)
T_a = np.array([[1, 0, 5, 1, 1],
                [0, 1, 4, 9, 1]], dtype=float)

# Pivot on column 3 (index 2), pivot row 1 (index 0): minimum ratio 1/5
T_a_pivot_x3 = T_a.copy()
pivot_col, pivot_row = 2, 0
# new_row2 = 5*row2 - 4*row1 (to zero column 3 in row 2)
T_a_pivot_x3[1] = T_a[1] * T_a[0, pivot_col] - T_a[0] * T_a[1, pivot_col]
print("T^(a) after pivot on x3 (col 3, row 1):")
print(T_a_pivot_x3)

# Pivot on column 4 (index 3) of T^(a), pivot row 2 (index 1): minimum ratio 1/9
T_a_pivot_x4 = T_a.copy()
pivot_col, pivot_row = 3, 1
# new_row1 = 9*row1 - row2 (to zero column 4 in row 1)
T_a_pivot_x4[0] = T_a[0] * T_a[1, pivot_col] - T_a[1] * T_a[0, pivot_col]
print("\nT^(a) after pivot on x4 (col 4, row 2):")
print(T_a_pivot_x4)
T^(a) after pivot on x3 (col 3, row 1):
[[ 1.  0.  5.  1.  1.]
 [-4.  5.  0. 41.  1.]]

T^(a) after pivot on x4 (col 4, row 2):
[[ 9. -1. 41.  0.  8.]
 [ 0.  1.  4.  9.  1.]]
# Tableau T^(b)
T_b = np.array([[4, 8, 1, 0, 1],
                [8, 1, 0, 1, 1]], dtype=float)

# Pivot on x1 (col 1, index 0), pivot row 2 (index 1): minimum ratio 1/8
T_b_pivot_x1 = T_b.copy()
pivot_col, pivot_row = 0, 1
T_b_pivot_x1[0] = T_b[0] * T_b[1, pivot_col] - T_b[1] * T_b[0, pivot_col]
print("T^(b) after pivot on x1 (col 1, row 2):")
print(T_b_pivot_x1)

# Pivot on x2 (col 2, index 1), pivot row 1 (index 0): minimum ratio 1/8
T_b_pivot_x2 = T_b.copy()
pivot_col, pivot_row = 1, 0
T_b_pivot_x2[1] = T_b[1] * T_b[0, pivot_col] - T_b[0] * T_b[1, pivot_col]
print("\nT^(b) after pivot on x2 (col 2, row 1):")
print(T_b_pivot_x2)
T^(b) after pivot on x1 (col 1, row 2):
[[ 0. 60.  8. -4.  4.]
 [ 8.  1.  0.  1.  1.]]

T^(b) after pivot on x2 (col 2, row 1):
[[ 4.  8.  1.  0.  1.]
 [60.  0. -1.  8.  7.]]
References
  1. Dantzig, G. B. (1947). Maximization of a Linear Function of Variables Subject to Linear Inequalities (Techreport P-38). Rand Corporation.
  2. Dantzig, G. B. (1951). Maximization of a linear function of variables subject to linear inequalities. Activity Analysis of Production and Allocation, 13, 339–347.
  3. Dantzig, G. B. (2020). Impact of linear programming on computer development. In Computers in Mathematics (pp. 233–240). CRC Press.
  4. Todd, M. J. (2002). The many facets of linear programming. Mathematical Programming, 91(3), 417–436.
  5. Adler, I. (2013). The equivalence of linear programs and zero-sum games. International Journal of Game Theory, 42, 165–177.
  6. Lemke, C. E., & Howson, J. T., Jr. (1964). Equilibrium points of bimatrix games. Journal of the Society for Industrial and Applied Mathematics, 12(2), 413–423.