Simplex pivots, Bland's rule and the lexicographic rule
DefinitionVanderbeiLP_Simplex_PivotRulesLet be a dictionary with basic set , nonbasic set and coefficients .
- An entering candidate is an index with . If there is none, the dictionary is optimal.
- For an entering variable , a leaving candidate is an index with whose ratio is minimal among all with . If no is positive, the problem is unbounded.
- A simplex pivot from to picks an entering candidate and a leaving candidate for it; the basic set of is .
- Bland's rule chooses both the entering and the leaving variable from their respective sets of candidates as the variable with the smallest index. A dictionary is terminal for this rule when there is no entering candidate, or the entering variable chosen by Bland's rule has for all .
- The lexicographic rule for a run started at the dictionary adds symbolic parameters all data to the right-hand sides of , one to each row. In a later dictionary the right-hand side of the row of becomes , and for the entering variable the rule chooses the leaving variable , , whose perturbed ratio
is minimal among the rows with . Because of the separation of scales, this comparison is the lexicographic comparison of the vectors . The entering variable is any entering candidate.
These are the pivoting rules whose termination is the subject of the mission.
Formalization Note The indices are ordered as Fin (n + m): decision variables before slacks , which is the order Bland's rule compares. For the lexicographic rule, is attached in to the row of its -th basic variable in increasing index order (for the initial dictionary, is added to the -th constraint, as on p. 29). The coefficient in the dictionary equals , where is that -th basic variable of ; the vectors are compared with Mathlib's lexicographic order toLex on Fin (m + 1) → ℝ.
import Mathlib
import Definitions.Def_VanderbeiLP_Simplex_Dictionary
namespace VanderbeiLP.Simplex
variable {m n : ℕ} {A : Matrix (Fin m) (Fin n) ℝ}
namespace Dictionary
/-- `x_k` is an **entering-variable candidate** of the dictionary `D` (Vanderbei, p. 15):
`k ∈ N` and `c̄_k > 0`. -/
def IsEnteringCandidate (D : Dictionary A) (c : Fin n → ℝ) (k : Fin (n + m)) : Prop :=
k ∉ D.B ∧ 0 < D.cbar c k
/-- `x_l` is a **leaving-variable candidate** for the entering variable `x_k` (p. 15): `l ∈ B`,
`ā_{lk} > 0`, and the ratio `b̄_l / ā_{lk}` is minimal among all `i ∈ B` with `ā_{ik} > 0`. -/
def IsLeavingCandidate (D : Dictionary A) (b : Fin m → ℝ) (k l : Fin (n + m)) : Prop :=
l ∈ D.B ∧ 0 < D.abar l k ∧
∀ i ∈ D.B, 0 < D.abar i k → D.bbar b l / D.abar l k ≤ D.bbar b i / D.abar i k
/-- One **pivot of the simplex method** (p. 15) takes `D` to `D'`: some entering candidate
`x_k` becomes basic and some leaving candidate `x_l` for it becomes nonbasic. -/
def IsSimplexPivot (b : Fin m → ℝ) (c : Fin n → ℝ) (D D' : Dictionary A) : Prop :=
∃ k l, D.IsEnteringCandidate c k ∧ D.IsLeavingCandidate b k l ∧
D'.B = insert k (D.B.erase l)
/-- **Bland's rule** for the entering variable (p. 31): `x_k` is the entering candidate with
the smallest index `k`. -/
def IsBlandEntering (D : Dictionary A) (c : Fin n → ℝ) (k : Fin (n + m)) : Prop :=
D.IsEnteringCandidate c k ∧ ∀ j, D.IsEnteringCandidate c j → k ≤ j
/-- **Bland's rule** for the leaving variable (p. 31): `x_l` is the leaving candidate for
`x_k` with the smallest index `l`. -/
def IsBlandLeaving (D : Dictionary A) (b : Fin m → ℝ) (k l : Fin (n + m)) : Prop :=
D.IsLeavingCandidate b k l ∧ ∀ i, D.IsLeavingCandidate b k i → l ≤ i
/-- A pivot from `D` to `D'` in which both the entering and the leaving variable are chosen by
Bland's rule. -/
def IsBlandPivot (b : Fin m → ℝ) (c : Fin n → ℝ) (D D' : Dictionary A) : Prop :=
∃ k l, D.IsBlandEntering c k ∧ D.IsBlandLeaving b k l ∧ D'.B = insert k (D.B.erase l)
/-- The two ways the simplex method under Bland's rule stops at `D` (pp. 15, 18–19): no
variable has `c̄_j > 0` (the dictionary is optimal), or the entering variable chosen by Bland's
rule has `ā_{ik} ≤ 0` for every `i ∈ B` (the problem is unbounded). -/
def IsBlandTerminal (D : Dictionary A) (c : Fin n → ℝ) : Prop :=
(∀ j, ¬ D.IsEnteringCandidate c j) ∨
∃ k, D.IsBlandEntering c k ∧ ∀ i ∈ D.B, D.abar i k ≤ 0
/-- The variable whose row receives the symbolic perturbation `ε_{p+1}` in the first
dictionary `D₀` of a run of the lexicographic method (p. 29): the basic variables of `D₀`
listed in increasing order of index. When `D₀` is the initial dictionary, `ε_{p+1}` is added
to the `(p+1)`-st constraint. -/
noncomputable def epsVar (D₀ : Dictionary A) (p : Fin m) : Fin (n + m) :=
D₀.B.orderEmbOfFin D₀.card_B p
/-- The perturbed right-hand side of the row of `x_i` in the dictionary `D` of the
lexicographic method started at `D₀` (p. 30), as the coefficient vector
`(b̄_i, r_{i1}, …, r_{im})` of `b̄_i + r_{i1} ε_1 + ⋯ + r_{im} ε_m`. -/
noncomputable def lexRow (D₀ D : Dictionary A) (b : Fin m → ℝ) (i : Fin (n + m)) :
Fin (m + 1) → ℝ :=
Fin.cons (D.bbar b i) (fun p => D.abar i (D₀.epsVar p))
/-- The **lexicographic rule** for the leaving variable (pp. 29–30), for the entering variable
`x_k`: `l ∈ B`, `ā_{lk} > 0`, and the perturbed ratio `(b̄_l + ∑_p r_{lp} ε_p)/ā_{lk}` is
minimal among all `i ∈ B` with `ā_{ik} > 0`, where the symbols satisfy
`0 < ε_m ≪ ⋯ ≪ ε_1 ≪` all data, i.e. the coefficient vectors are compared lexicographically. -/
def IsLexLeaving (D₀ D : Dictionary A) (b : Fin m → ℝ) (k l : Fin (n + m)) : Prop :=
l ∈ D.B ∧ 0 < D.abar l k ∧
∀ i ∈ D.B, 0 < D.abar i k →
toLex ((D.abar l k)⁻¹ • lexRow D₀ D b l) ≤ toLex ((D.abar i k)⁻¹ • lexRow D₀ D b i)
/-- A pivot from `D` to `D'` of the lexicographic method started at `D₀`: any entering
candidate `x_k`, and the leaving variable chosen by the lexicographic rule. -/
def IsLexPivot (D₀ : Dictionary A) (b : Fin m → ℝ) (c : Fin n → ℝ) (D D' : Dictionary A) :
Prop :=
∃ k l, D.IsEnteringCandidate c k ∧ IsLexLeaving D₀ D b k l ∧ D'.B = insert k (D.B.erase l)
end Dictionary
end VanderbeiLP.Simplex