Executable Bareiss determinant algorithm for hex-matrix.
This module implements fraction-free Bareiss elimination over Int in two
layers: a no-pivot recurrence that follows the standard exact-division update,
and a public row-pivoting wrapper that swaps in a nonzero pivot when needed and
tracks the resulting determinant sign. The Mathlib-free layer exposes the
executable data and state needed by later bridge proofs; it does not expose a
theorem identifying the executable Bareiss determinant with the generic
Leibniz determinant.
Output of an executable Bareiss elimination pass.
Terminal matrix produced by the Bareiss pass. When
singularStep = none,BareissData.detreads the last diagonal entry of this matrix, with the row-swap sign applied; forn = 0, the empty diagonal contributes1.- rowSwaps : Nat
Number of row swaps performed by pivoting. Even parity contributes sign
1; odd parity contributes sign-1. The first elimination step that found a zero pivot and no replacement row. A value
some krecords that singular step and makesBareissData.detreturn0;nonemeans the run reached the terminal diagonal encoding.
Instances For
The determinant encoded by a Bareiss elimination result.
Equations
Instances For
A recorded singular step encodes determinant zero.
For a non-singular Bareiss elimination of an empty matrix, the encoded determinant is the sign.
Internal state of the no-pivot Bareiss recurrence, exposed read-only for the Mathlib-side determinant proof.
- step : Nat
Current elimination step. The next update, if any, uses this row and column as the pivot position.
Current matrix carried by the Bareiss recurrence. Its terminal value is copied into
BareissData.matrixbyfinish.- prevPivot : Int
Previous nonzero pivot used as the exact-division denominator; initially
1. - rowSwaps : Nat
Number of row swaps already performed by the pivoting wrapper. Even parity contributes determinant sign
1; odd parity contributes sign-1. First step at which the recurrence found a zero pivot and could not continue. A value
some kis terminal evidence for the determinant-zero encoding;nonemeans no singular step has been recorded.
Instances For
Exact division used by the Bareiss recurrence.
Divisibility holds at every call site by the algorithmic invariant, so
this function performs no runtime divisibility check: the @[extern]
binding compiles the call directly to lean_int_div_exact, matching
Int.divExact. The Lean-level reduction is the same num / denom that
Int.divExact uses as its logical model.
Equations
- Hex.Matrix.exactDiv num denom = num / denom
Instances For
Search column col for a nonzero pivot at or below start.
Equations
- M.findPivot? col start = M.findPivotAux col start (n - start)
Instances For
A pivot returned by findPivotAux is always at or below its starting row.
A pivot returned by findPivot? is always at or below its starting row.
If bounded pivot search fails, every checked entry in the pivot column is zero.
If every entry in the suffix searched by findPivot? is zero, pivot
search fails. This is the converse of findPivot?_eq_zero_of_none and lets
callers turn a column-zero invariant into the executable no-replacement-pivot
condition used by pivotLoop.
A pivot returned by findPivot? indexes a nonzero entry in the pivot
column. Lets row-pivoted Bareiss callers read off the nonzero post-swap pivot
without unfolding the findPivotAux recursion.
Apply one Bareiss update step to the trailing submatrix strictly below and to the right of the current pivot.
Built in place: rows at or above the pivot (i ≤ k) are left untouched, and only
the rows below the pivot are rebuilt, via mapRowsIdx threading the matrix
through per-row Vector.modifys. The pivot row is read once into pivotRow
before the scatter (it is never mutated, since only rows i > k change), so the
update reuses the outer vector and the finished prefix rows rather than
reallocating the whole n × n matrix as a fresh ofFn.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The in-place stepMatrix agrees entrywise with the ofFn form it replaces;
lets the existing entry lemmas reduce through the same body.
If the current matrix entries already match bordered minors and exact
division evaluates to the next bordered minor, then one stepMatrix update
preserves the bordered-minor invariant at the updated entry.
Exact-division equation for one Bareiss bordered-minor update.
Once a determinant identity supplies the numerator as nextMinor * prevPivot,
this lemma packages it as the exactDiv premise expected by
stepMatrix_borderedMinor_update.
Read an entry from an Array (Array Int) row-storage representation.
Exposed so downstream Mathlib-free clients (notably the shared scaled
Gram-Schmidt loop in HexGramSchmidt.Int) can speak about array storage
without re-deriving the conversion lemmas.
Instances For
Unpack an Array (Array Int) row-storage representation back into a
Matrix Int n n. Inverse-on-the-left of matrixToRows.
Equations
- Hex.Matrix.rowsToMatrix rows n = Hex.Matrix.ofFn fun (i j : Fin n) => Hex.Matrix.getEntry rows ↑i ↑j
Instances For
Reading back the array storage produced by matrixToRows recovers the
original matrix.
Bareiss elimination with row pivoting. If a column has no nonzero pivot, the elimination aborts and the determinant is zero.
Equations
- One or more equations did not get rendered due to their size.
- Hex.Matrix.pivotLoop 0 state = state
Instances For
With zero fuel, the row-pivoted Bareiss loop returns its input state.
If the current row-pivoted Bareiss pivot is already nonzero, one loop
iteration applies stepMatrix, advances the step, and recurses without
changing the row-swap counter.
If the current pivot is zero and pivot search finds no replacement row, the row-pivoted Bareiss loop records a singular step.
If the current pivot is zero, pivot search finds a replacement row, and
the swapped pivot is nonzero, one loop iteration swaps rows, applies
stepMatrix, advances the step, increments the row-swap counter, and recurses.
bareissArrayState runs the matrix-level Bareiss elimination via pivotLoop
and repackages the reduced result as a BareissArrayState, storing the matrix
row-by-row via matrixToRows.
Equations
- One or more equations did not get rendered due to their size.
Instances For
arrayLastDiag? reads the last diagonal entry (n-1, n-1) of the reduced
rows, returning none when n = 0.
Equations
- Hex.Matrix.arrayLastDiag? rows 0 = none
- Hex.Matrix.arrayLastDiag? rows fuel_1.succ = some (Hex.Matrix.getEntry rows fuel_1 fuel_1)
Instances For
bareissArrayDet assembles the determinant value from the final array
state, returning 0 when elimination recorded a singular column and the signed
last diagonal entry otherwise.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Package a Bareiss state as public elimination data.
Equations
- Hex.Matrix.finish state = { matrix := state.matrix, rowSwaps := state.rowSwaps, singularStep := state.singularStep }
Instances For
Bareiss elimination without pivoting. A zero pivot aborts and records the singular step.
Equations
- One or more equations did not get rendered due to their size.
- Hex.Matrix.noPivotLoop 0 state = state
Instances For
With zero fuel, the no-pivot Bareiss loop returns its input state.
If the current step is already past the last update step, the no-pivot loop returns its input state.
If the current no-pivot Bareiss pivot is nonzero, one loop iteration applies
stepMatrix, advances the step, and recurses on the remaining fuel.
Entries in rows already processed, or in columns strictly before the current step, are unchanged by subsequent no-pivot loop iterations.
The no-pivot loop never changes the row-swap counter.
Once a no-pivot Bareiss state is already at the terminal step boundary, additional fuel leaves it unchanged.
Once a no-pivot Bareiss state has recorded a zero pivot at the current step, additional fuel leaves that singular fixed point unchanged.
Fuel composition for the no-pivot Bareiss loop: running a + b units of
fuel from state equals running b more units after a initial units.
When a no-pivot Bareiss run records no singular step and has enough room,
the step field advances by exactly the amount of consumed fuel.
When the no-pivot Bareiss loop completes fuel iterations without
recording a singular step, the row-pivoted Bareiss loop produces an
identical state: every diagonal pivot is nonzero, so the row search and
swap branches of pivotLoop are never entered and both loops apply the
same stepMatrix updates.
Initial state used by the no-pivot Bareiss recurrence.
Equations
- M.noPivotInitialState = { step := 0, matrix := M, prevPivot := 1, rowSwaps := 0, singularStep := none }
Instances For
Run the no-pivot Bareiss recurrence and return the final elimination data.
Equations
Instances For
Determinant computed by the no-pivot Bareiss recurrence.
Equations
Instances For
Run the row-pivoted Bareiss elimination and return the final elimination data together with the swap/sign bookkeeping.
Equations
- M.bareissData = { matrix := Hex.Matrix.rowsToMatrix M.bareissArrayState.matrix n, rowSwaps := M.bareissArrayState.rowSwaps, singularStep := M.bareissArrayState.singularStep }
Instances For
The packaged row-pivoted Bareiss data is exactly the structured pivot loop
state finished into public determinant data. This is the equality consumed by the
Mathlib determinant proof; array storage is erased by rowsToMatrix.
Determinant computed by the row-pivoted Bareiss algorithm.
Equations
Instances For
The public row-pivoted determinant agrees with the determinant encoded by
bareissData. This separates executable array evaluation from the packaged
elimination data used by correctness proofs.
If the no-pivot Bareiss pass reaches the final pivot without recording a
singular step, then the public row-pivoted bareiss determinant is exactly
the no-pivot final diagonal entry.