Skip to content

Prove Gantmacher-Krein for matrices with primitive compounds - #414

Merged
PerAlexandersson merged 9 commits into
mainfrom
proof/gk-primitive-compounds
Aug 22, 2026
Merged

Prove Gantmacher-Krein for matrices with primitive compounds#414
PerAlexandersson merged 9 commits into
mainfrom
proof/gk-primitive-compounds

Conversation

@PerAlexandersson

Copy link
Copy Markdown
Owner

Stacked on #411 and #412 (this branch merges both; review the last commit —
GantmacherKrein.lean — the rest lands with those PRs).

exists_charpoly_eq_prod_of_forall_compound_primitive: if every compound
compound q A of a real matrix is primitive, then

∃ μ : Fin n → ℝ, (∀ i, 0 < μ i) ∧ A.charpoly = ∏ i, (X - C (μ i))

— the characteristic polynomial splits over ℝ with strictly positive roots.
This is the oscillatory case of Gantmacher–Krein, proved without Whitney
density or root continuity: strict spectral dominance for primitive matrices
forces the sorted top-q eigenvalue product to equal the Perron root of the
q-th compound (otherwise its modulus is simultaneously < ρ_q and ≥ ρ_q),
so every μ_q = ρ_q/ρ_{q−1} is real positive. The tie obstruction that blocks
the naive argument for general TN matrices (see #394: the multiset {1, i, −i})
never arises.

Chain consumed: #411 (exists_charpoly_compound_eq_prod) + #412
(exists_nonneg_mulVec_eq_perronRoot_smul, spectral_dominance_of_primitive',
perronRoot_pos_of_irreducible).

Supporting lemmas: compound_map, prod_powersetEnum,
prod_powersetCard_comp_perm, and a topFinset initial-segment kit.

Sorry-free; full library builds (9020 jobs).

🤖 Generated with Claude Code

PerAlexandersson and others added 9 commits August 21, 2026 16:20
The triangular half of the compound eigenvalue theorem (issue #405 item 3):

- `BlockTriangular.det_of_injective`, `BlockTriangular.charpoly_of_injective`:
  a block triangular matrix with an injective block map has determinant and
  characteristic polynomial given by its diagonal (generalizes
  `Matrix.det_of_upperTriangular` to indices without a linear order);
- `compound_apply_eq_zero_of_blockTriangular`: minors of an upper triangular
  matrix vanish unless the row selection is pointwise dominated by the column
  selection (permutation expansion plus a pigeonhole step);
- `powersetCode`: the binary encoding of a selection, injective via Mathlib's
  colex `Finset.geomSum_injective`, monotone for pointwise domination;
- `blockTriangular_compound`, `compound_apply_self_of_blockTriangular`,
  `charpoly_compound_of_blockTriangular`: the compound of a triangular matrix
  is triangular for the binary encoding, with diagonal the selected products,
  so its charpoly is `∏_s (X - C ∏_{i ∈ s} T i i)`;
- `compound_one`, `charpoly_compound_conj`: the compound charpoly is invariant
  under conjugation, by multiplicativity.

What remains for the full eigenvalue statement is matrix-level
triangularization over an algebraically closed field, which Mathlib lacks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes the mathematical content of issue #405: over an algebraically closed
field there is an enumeration mu of the eigenvalues of A (with multiplicity)
such that for every q the characteristic polynomial of `compound q A` is
`prod_s (X - C (prod_{i in s} mu i))` over the increasing q-selections.

Pure assembly of the two merged halves plus one new ingredient:

- triangularize A (`exists_unitsConj_blockTriangular`, #410);
- sort the height function of the triangular form into the index order by a
  permutation-matrix conjugation (`Tuple.sort` + `permMatrixHom.toHomUnits` +
  `PEquiv.toMatrix_toPEquiv_mul` / `PEquiv.mul_toMatrix_toPEquiv`);
- read off the compound charpoly of the sorted triangular form
  (`charpoly_compound_of_blockTriangular`), transporting along both
  conjugations with `charpoly_compound_conj` and `charpoly_units_conj`.

This is the spectral input Gantmacher-Krein (#394) consumes: TN matrices have
entrywise nonnegative compounds, so Perron-Frobenius (#404) on each compound
controls the eigenvalue products.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ports the Perron-Frobenius formalization from or4nge19/MCMC
(MCMC/PF, commit dba8102f, Apache-2.0, author Matteo Cipollina) into
RealRooted/Mathlib/LinearAlgebra/Matrix/PerronFrobenius/, adapted to the
pinned Mathlib (the original targeted a 2026-01 Mathlib; ours is 2026-06).

Twelve files, ~6100 lines, sorry-free:
DataList, QuiverPath, Spectrum, ExtremeValueUSC, CStarClasses, Auxiliary,
Lemmas, CollatzWielandt, Primitive, Uniqueness, Irreducible, Dominance.

Key theorems now available (issue #404):
- `Matrix.pft_irreducible`: an irreducible nonnegative real matrix has a
  unique stdSimplex-normalized eigenvector, with positive eigenvalue;
- `Matrix.perron_root_is_eigenvalue`: the Perron root of an irreducible
  nonnegative matrix is an eigenvalue;
- `Matrix.eigenvalue_abs_le_perron_root`: every complex eigenvalue has
  modulus at most the Perron root;
- the Collatz-Wielandt variational theory backing them.

Adaptations for five months of Mathlib drift:
- `Matrix.toQuiver` arrows became `PLift (0 < A i j)`: inserted `.down` /
  `⟨_⟩` at eight use sites;
- `List.dropLast_cons_cons` upstreamed: dropped the local copy;
- `stdSimplex` argument order: `isCompact_stdSimplex ℝ n`;
- `inferInstanceAs (Nonempty n)` under postponed elaboration: replaced by
  anonymous-hypothesis syntax;
- `Path.end` is now definitional: replaced dead `simpa`s by `exact`/`rfl`
  terms and repaired one `subst`-sensitive case split;
- deprecated import `Data.Real.StarOrdered` -> `Algebra.Order.Star.Real`;
- dropped two upstream-`sorry`d `spectralRadius` bridge theorems in
  Dominance (not needed by Gantmacher-Krein, which uses `perronRoot`
  directly) and one unused upstream-`sorry`d Quiver lemma;
- `Aux.lean` renamed `Auxiliary.lean` (reserved file name).

Ported files keep their original line layout
(`set_option linter.style.longLine false`).

Remaining for #404 / #394: the general (reducible) nonnegative case via the
`A + eps J` limit, in a follow-up file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds PerronFrobenius/Nonneg.lean, removing the irreducibility hypothesis --
the form Gantmacher-Krein (#394) needs, since compounds of totally
nonnegative matrices are entrywise nonnegative but not irreducible.

- `isIrreducible_of_pos`: an entrywise positive matrix is irreducible
  (single-edge paths in the positivity quiver);
- `perronRoot_le_perronRoot_of_le`: entrywise matrix monotonicity of the
  Perron root, via `le_mulVec` -> `le_of_subinvariant` ->
  `collatzWielandtFn_le_perronRoot`;
- `norm_le_perronRoot_of_eigenvalue`: every complex eigenvalue of a
  nonnegative real matrix has modulus at most the Perron root, with no
  irreducibility -- the ported subinvariance inequalities
  (`eigenvalue_abs_subinvariant`, `le_of_subinvariant`) never needed it;
- `exists_nonneg_mulVec_eq_perronRoot_smul`: **the general theorem** -- a
  nonnegative matrix attains its Perron root as an eigenvalue with a
  nonnegative eigenvector.  Proof: perturb to `A + ((k:R)+1)^-1 * J` (positive,
  hence irreducible), apply `perron_root_eq_positive_eigenvalue`, normalize
  eigenvectors to the standard simplex, extract a convergent subsequence in
  the compact set `Icc (perronRoot A) M x stdSimplex` and pass to the limit;
  the limit eigenvalue is squeezed to `perronRoot A` by matrix monotonicity
  from below and subinvariance from above.

Together with the port this completes the mathematical content of #404.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds RealRooted/Mathlib/LinearAlgebra/Matrix/GantmacherKrein.lean, the
density-free case of Gantmacher-Krein:

  `exists_charpoly_eq_prod_of_forall_compound_primitive`:
  if every compound `compound q A` (1 <= q <= n) of a real matrix `A` is
  primitive, then `A.charpoly = prod_i (X - C (mu i))` with all `mu i > 0`.

This covers the oscillatory case.  The argument needs no tie analysis: sort a
complex eigenvalue enumeration (from `exists_charpoly_compound_eq_prod`) by
descending modulus; for each q the Perron root of `compound q A` is an
attained selection product (general PF, `mem_spectrum_iff_isRoot_charpoly`),
and by strict spectral dominance for primitive matrices
(`spectral_dominance_of_primitive'`) the top product must equal it -- else
its modulus would be simultaneously strictly below and at least the Perron
root.  Hence every partial product mu_1 ... mu_q equals the q-th Perron root,
and mu_q is the quotient of consecutive Perron roots, real and positive.
Injectivity of `Polynomial.map` along `algebraMap R C` brings the
factorization back to the reals.

Supporting lemmas: `compound_map` (compounds commute with entrywise ring
homomorphisms), `prod_powersetEnum` (selection products as finite-set
products), `prod_powersetCard_comp_perm` (permutation invariance of the
compound factorization), and the `topFinset` initial-segment kit.

The general totally nonnegative case additionally needs Whitney density and
root continuity (see #394 for the corrected roadmap).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- `compound_pow`: compounds commute with matrix powers;
- `isPrimitive_compound_of_pow`: a totally nonnegative matrix, some power of
  which has strictly positive compound entries (the oscillatory situation),
  has all compounds primitive;
- `exists_charpoly_eq_prod_of_pow_compound_pos`: oscillatory matrices have
  real positive spectrum;
- `charpoly_splits_of_forall_compound_primitive`: the splitting form --
  `A.charpoly.Splits` with all roots strictly positive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@PerAlexandersson

Copy link
Copy Markdown
Owner Author

Added the oscillatory bridge on the same branch: compound_pow, isPrimitive_compound_of_pow (TN + some power has positive compound entries ⟹ all compounds primitive), exists_charpoly_eq_prod_of_pow_compound_pos (oscillatory matrices have real positive spectrum), and the splitting form charpoly_splits_of_forall_compound_primitive (A.charpoly.Splits with strictly positive roots).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant