Skip to content
Browse chapters
Imports

29.3 Bland's anti-cycling theorem

This is the textbook greatest-fickle-variable proof. Assuming a repeated basis, it compares two equivalent objective expressions and constructs a smaller-index minimum-ratio row, contradicting Bland's leaving tie break.

namespace CLRSnamespace Chapter29namespace Dictionary

Bland-rule SIMPLEX never repeats a basis along a nonempty feasible pivot trace.

theorem bland_no_repeated_basis {D F : Dictionary m n} (hD : D.IsBasicFeasible) (hcycle : Relation.TransGen IsBlandPivot D F) : D.basicVariables ≠ F.basicVariables := by intro hbasis let hne := fickleVariables_nonempty_of_cycle hcycle let ell := D.greatestFickle F hne have hellmem : ell ∈ D.fickleVariables F := D.greatestFickle_mem F hne have hell : D.IsFickle F ell := (D.mem_fickleVariables F ell).1 hellmem obtain ⟨E, hEon, hchange⟩ := hell have hsteps : (∃ (P P' : Dictionary m n) (p : BlandPivot P P'), BlandReachable D P ∧ BlandReachable P' F ∧ ell = P.basicVar p.leaving) ∧ (∃ (Q Q' : Dictionary m n) (q : BlandPivot Q Q'), BlandReachable D Q ∧ BlandReachable Q' F ∧ ell = Q.nonbasicVar q.entering) := by rcases hchange with ⟨hellD, hellE⟩ | ⟨hellD, hellE⟩ · have hellF : ell ∈ F.basicVariables := by rw [← hbasis] exact hellD obtain ⟨P, P', p, hDP, hP'E, hpell⟩ := hEon.1.exists_leaving_of_mem_not_mem hellD hellE obtain ⟨Q, Q', q, hEQ, hQ'F, hqell⟩ := hEon.2.exists_entering_of_not_mem_mem hellE hellF exact ⟨ ⟨P, P', p, hDP, hP'E.trans hEon.2, hpell⟩, ⟨Q, Q', q, hEon.1.trans hEQ, hQ'F, hqell⟩⟩ · have hellF : ell ∉ F.basicVariables := by rw [← hbasis] exact hellD obtain ⟨Q, Q', q, hDQ, hQ'E, hqell⟩ := hEon.1.exists_entering_of_not_mem_mem hellD hellE obtain ⟨P, P', p, hEP, hP'F, hpell⟩ := hEon.2.exists_leaving_of_mem_not_mem hellE hellF exact ⟨ ⟨P, P', p, hEon.1.trans hEP, hP'F, hpell⟩, ⟨Q, Q', q, hDQ, hQ'E.trans hEon.2, hqell⟩⟩ obtain ⟨⟨P, P', p, hDP, hP'F, hpell⟩, ⟨Q, Q', q, hDQ, hQ'F, hqell⟩⟩ := hsteps let hvar := P.nonbasicVar p.entering have hhfickle : D.IsFickle F hvar := isFickle_entering hDP p hP'F have hhmem : hvar ∈ D.fickleVariables F := (D.mem_fickleVariables F hvar).2 hhfickle have hhle : variableIndex hvar ≤ variableIndex ell := D.variableIndex_le_greatestFickle F hne hhmem have hhne : hvar ≠ ell := by intro hheq have hbad : P.basicVar p.leaving = P.nonbasicVar p.entering := hpell.symm.trans hheq.symm exact P.labels_basic_ne_nonbasic p.leaving p.entering hbad have hhidxne : variableIndex hvar ≠ variableIndex ell := by intro hidx exact hhne (variableIndex_injective hidx) have hhlt : variableIndex hvar < variableIndex ell := lt_of_le_of_ne hhle hhidxne have hhltQ : variableIndex hvar < Q.nonbasicVariableIndex q.entering := by change variableIndex hvar < variableIndex (Q.nonbasicVar q.entering) rw [← hqell] exact hhlt have hhcoeff : Q.objectiveCoeff hvar ≤ 0 := q.enteringIsBland.objectiveCoeff_nonpos_of_index_lt hhltQ have hPQ : P.Equivalent Q := hDP.equivalent.symm.trans hDQ.equivalent have hidentity := hPQ.entering_coefficient_identity p.entering obtain ⟨i, hineg⟩ := P.exists_negative_coefficient_product Q p.entering hidentity p.enteringIsBland.1 hhcoeff let ivar := P.basicVar i have hicoeffne : Q.objectiveCoeff ivar ≠ 0 := by intro hzero rw [hzero, zero_mul] at hineg exact (lt_irrefl 0) hineg have hiQnot : ivar ∉ Q.basicVariables := Q.not_mem_basicVariables_of_objectiveCoeff_ne_zero hicoeffne have hiPmem : ivar ∈ P.basicVariables := P.basicVar_mem_basicVariables i have hifickle : D.IsFickle F ivar := by by_cases hiD : ivar ∈ D.basicVariables · exact ⟨Q, ⟨hDQ, (BlandReachable.single q).trans hQ'F⟩, Or.inl ⟨hiD, hiQnot⟩⟩ · exact ⟨P, ⟨hDP, (BlandReachable.single p).trans hP'F⟩, Or.inr ⟨hiD, hiPmem⟩⟩ have himem : ivar ∈ D.fickleVariables F := (D.mem_fickleVariables F ivar).2 hifickle have hile : variableIndex ivar ≤ variableIndex ell := D.variableIndex_le_greatestFickle F hne himem have hcoeffell : 0 < Q.objectiveCoeff ell := by rw [hqell, Q.objectiveCoeff_nonbasicVar] exact q.enteringIsBland.1 have hine : ivar ≠ ell := by intro hieq have hibasic : P.basicVar i = P.basicVar p.leaving := hieq.trans hpell have hirow : i = p.leaving := by have hslots := P.labels.injective hibasic exact Sum.inl_injective hslots have hpositive : 0 < Q.objectiveCoeff ivar * P.a i p.entering := by rw [hieq, hirow] exact mul_pos hcoeffell p.leavingIsBland.1.pivotCoefficient_pos exact (not_lt_of_ge hpositive.le) hineg have hiidxne : variableIndex ivar ≠ variableIndex ell := by intro hidx exact hine (variableIndex_injective hidx) have hilt : variableIndex ivar < variableIndex ell := lt_of_le_of_ne hile hiidxne have hiltQ : variableIndex ivar < Q.nonbasicVariableIndex q.entering := by change variableIndex ivar < variableIndex (Q.nonbasicVar q.entering) rw [← hqell] exact hilt have hicoeff : Q.objectiveCoeff ivar ≤ 0 := q.enteringIsBland.objectiveCoeff_nonpos_of_index_lt hiltQ have hia : 0 < P.a i p.entering := by by_contra hnot have hnonpos : P.a i p.entering ≤ 0 := le_of_not_gt hnot have hprod : 0 ≤ Q.objectiveCoeff ivar * P.a i p.entering := mul_nonneg_of_nonpos_of_nonpos hicoeff hnonpos exact (not_lt_of_ge hprod) hineg have hPon : OnBlandPath D P F := ⟨hDP, (BlandReachable.single p).trans hP'F⟩ have hQon : OnBlandPath D Q F := ⟨hDQ, (BlandReachable.single q).trans hQ'F⟩ have hbasicPQ : P.basicAssignment = Q.basicAssignment := (hPon.basicAssignment_eq_of_closedBasis hD hbasis).symm.trans (hQon.basicAssignment_eq_of_closedBasis hD hbasis) have hibzero : P.b i = 0 := by calc P.b i = P.basicAssignment ivar := (P.basicAssignment_basicVar i).symm _ = Q.basicAssignment ivar := congrFun hbasicPQ ivar _ = 0 := Q.basicAssignment_eq_zero_of_not_mem_basicVariables hiQnot have hPfeasible : P.IsBasicFeasible := hDP.isBasicFeasible hD have himin : P.IsMinimumRatio p.entering i := by refine ⟨hia, ?_⟩ intro k hk rw [hibzero, zero_div] exact div_nonneg (hPfeasible k) hk.le have hleaveIndex : P.basicVariableIndex p.leaving ≤ P.basicVariableIndex i := p.leavingIsBland.2 i himin have hiIndex : P.basicVariableIndex i < P.basicVariableIndex p.leaving := by change variableIndex ivar < variableIndex (P.basicVar p.leaving) rw [← hpell] exact hilt exact (not_lt_of_ge hleaveIndex) hiIndex

In particular, a feasible Bland-pivot relation has no directed cycle.

theorem bland_acyclic (D : Dictionary m n) (hD : D.IsBasicFeasible) : ¬Relation.TransGen IsBlandPivot D D := by intro hcycle exact D.bland_no_repeated_basis hD hcycle rfl
end Dictionaryend Chapter29end CLRS