/- Copyright (c) 2024 Judith Ludwig, Christian Merten. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Judith Ludwig, Christian Merten -/ import BruhatTits.Lattice.Distance import BruhatTits.Lattice.Construction /-! # Definition of vertices In this file we define the type of vertices of the Bruhat-Tits tree. A vertex is an equivalence class of `R`-lattices with respect to homothety. The distance of lattices is invariant under homothety (see `BruhatTits.dist_inv_isSimilar`), hence the distance function descends to vertices which is called `BruhatTits.inv`. This is later used to define the edge relations on the Bruhat-Tits graph (see `BruhatTits.Graph.Edges`). ## Main definitions and results - `BruhatTits.inv`: the distance between vertices defined as the distance between lattice representatives. - `BruhatTits.exists_repr_inv'`: given two vertices `x` and `y`, there exists a basis `b` of `Fin 2 → K` such that `x = ⟦b.toLattice⟧` and `y = `⟦(b.ntwist₂ (inv x y) 0).toLattice⟧`. - `BruhatTits.exists_intermediate_vertex`: Given two vertices `x` and `y` of distance `n + 1`, there exists a vertex `z` such that `inv x z = n` and `inv z y = 1`. This will later be used to deduce that the Bruhat-Tits graph is connected. -/ namespace BruhatTits variable {K : Type*} [Field K] (R : Subring K) [IsDiscreteValuationRing R] [IsFractionRing R K] /-- The vertices of the Bruhat-Tits tree are `R`-lattices modulo the equivalence relation `IsSimilar`. -/ def Vertices : Type _ := Quotient (Lattice.IsSimilar.setoid R) variable {R} /-- An abbreviation for `Quotient.mk` for vertices. We only use this it the additional type information is needed. -/ abbrev Vertices.mk (L : Lattice R) : Vertices R := ⟦L⟧ /-- The distance of vertices defined as the distance of representatives. This is well-defined by `BruhatTits.dist_inv_isSimilar`. -/ noncomputable def inv (L M : Vertices R) : ℕ := Quotient.lift₂ dist dist_inv_isSimilar L M @[simp] lemma inv_mk (L M : BruhatTits.Lattice R) : inv (Quotient.mk'' L) (Quotient.mk'' M) = dist L M := rfl lemma inv_symm (L M : Vertices R) : inv L M = inv M L := by refine Quotient.inductionOn₂' L M (fun L M ↦ ?_) simp only [inv_mk] exact dist_symm L M lemma inv_self (L : Vertices R) : inv L L = 0 := by refine Quotient.inductionOn' L (fun L ↦ ?_) simp open Pointwise LocalRing /-- Variant of `exists_repr_inv` where the first vertex has a fixed representative. -/ lemma exists_repr_inv_of_fixed (M : Lattice R) (y : Vertices R) : ∃ (ϖ : R) (_ : Irreducible ϖ) (L : Lattice R) (bM : Basis (Fin 2) R M.M) (bL : Basis (Fin 2) R L.M), ⟦L⟧ = y ∧ bL 0 = ϖ ^ (inv ⟦M⟧ y) • (bM 0).val ∧ bL 1 = (bM 1).val := by refine Quotient.inductionOn' y (fun L ↦ ?_) obtain ⟨ϖ, bM, bL, f, hϖ, _, hrep, hdiff⟩ := exists_repr_dist M L have hϖ' : ϖ.val ≠ 0 := by simpa using hϖ.ne_zero let L' : Lattice R := (Units.mk0 ϖ.val hϖ') ^ (- f 1) • L let bL' : Basis (Fin 2) R L'.M := mulBasisScalar ((Units.mk0 ϖ.val hϖ') ^ (-f 1)) bL refine ⟨ϖ, hϖ, L', bM, bL', ?_, ?_, ?_⟩ · simpa [L'] using Lattice.smul_isSimilar R L _ · simp only [bL', hrep 0] rw [mulBasisScalar_apply, Units.val_zpow_eq_zpow_val, Units.val_mk0, inv_mk, hrep, smul_smul, ← zpow_add₀ hϖ', neg_add_eq_sub, hdiff, R.smul_def, R.coe_pow, zpow_natCast] · simp only [bL', hrep 1] rw [mulBasisScalar_apply, Units.val_zpow_eq_zpow_val, Units.val_mk0, hrep, smul_smul, ← zpow_add₀ hϖ', neg_add_eq_sub, sub_self, zpow_zero, one_smul] /-- Given vertices `x` and `y`, there exist representatives `M` and `L` and a basis `bM` of `M` such that `(ϖ ^ (inv x y) • (bM 0), bM 1)` is a basis of `L`. -/ lemma exists_repr_inv (x y : Vertices R) : ∃ (ϖ : R) (_ : Irreducible ϖ) (M L : Lattice R) (bM : Basis (Fin 2) R M.M) (bL : Basis (Fin 2) R L.M), ⟦M⟧ = x ∧ ⟦L⟧ = y ∧ bL 0 = ϖ ^ (inv x y) • (bM 0).val ∧ bL 1 = (bM 1).val := by refine Quotient.inductionOn' x (fun M ↦ ?_) obtain ⟨ϖ, hϖ, L, bM, bL, hL, hbL₀, hbL₁⟩ := exists_repr_inv_of_fixed M y use ϖ, hϖ, M, L, bM, bL /-- Variant of `exists_repr_dist` in terms of `Basis.twist`. -/ lemma exists_repr_dist' (M L : Lattice R) : ∃ (ϖ : R) (hϖ : Irreducible ϖ) (b : Basis (Fin 2) K (Fin 2 → K)) (f : Fin 2 → ℤ) (_ : Antitone f), M = b.toLattice ∧ L = (b.twist hϖ f).toLattice ∧ f 0 - f 1 = dist M L := by obtain ⟨ϖ, bM, bL, f, hϖ, hf, hrep, hdiff⟩ := exists_repr_dist M L have hML : bM.fromLattice.twist hϖ f = bL.fromLattice := by ext i : 1 simp [hrep] refine ⟨ϖ, hϖ, bM.fromLattice, f, hf, ?_, ?_, hdiff⟩ · simp · simp [hML] /-- Variant of `exists_repr_inv_of_fixed` in terms of `Basis.ntwist₂`. -/ lemma exists_repr_inv'_of_fixed (M : Lattice R) (L : Vertices R) : ∃ (ϖ : R) (hϖ : Irreducible ϖ) (b : Basis (Fin 2) K (Fin 2 → K)), b.toLattice = M ∧ ⟦(b.ntwist₂ hϖ (inv ⟦M⟧ L) 0).toLattice⟧ = L := by refine Quotient.inductionOn' L (fun L ↦ ?_) obtain ⟨ϖ, hϖ, L', bM, bL, hL, h0, h1⟩ := exists_repr_inv_of_fixed M ⟦L⟧ have hML : bM.fromLattice.ntwist₂ hϖ (inv ⟦M⟧ (Quotient.mk'' L)) 0 = bL.fromLattice := by ext i : 1 simp only [inv_mk, Basis.fromLattice_apply] match i with | 0 => simp only [Basis.ntwist₂_apply₀, Basis.fromLattice_apply, h0]; rfl | 1 => simp [h1] refine ⟨ϖ, hϖ, bM.fromLattice, ?_, ?_⟩ · simp only [Basis.toLattice_fromLattice] · rw [hML] simp only [Basis.toLattice_fromLattice, hL] /-- Variant of `exists_repr_inv` in terms of `Basis.ntwist₂`. -/ lemma exists_repr_inv' (M L : Vertices R) : ∃ (ϖ : R) (hϖ : Irreducible ϖ) (b : Basis (Fin 2) K (Fin 2 → K)), ⟦b.toLattice⟧ = M ∧ ⟦(b.ntwist₂ hϖ (inv M L) 0).toLattice⟧ = L := by refine Quotient.inductionOn' M (fun M ↦ ?_) obtain ⟨ϖ, hϖ, b, rfl, hL⟩ := exists_repr_inv'_of_fixed M L use ϖ, hϖ, b /-- If `b` is a basis of `Fin 2 → K` and `f₀ ≥ f₁`, the distance of `b.toLattice` and `(b.twist hϖ f).toLattice` is `f₀ - f₁`. -/ lemma dist_twist (b : Basis (Fin 2) K (Fin 2 → K)) {ϖ : R} (hϖ : Irreducible ϖ) {f : Fin 2 → ℤ} (hf : Antitone f) : dist b.toLattice (R := R) (b.twist hϖ f).toLattice = f 0 - f 1 := by have hcast : f 0 - f 1 = ↑(f 0 - f 1).toNat := (Int.toNat_sub_of_le <| hf (by simp)).symm have : dist b.toLattice (R := R) (b.twist hϖ f).toLattice = (f 0 - f 1).toNat := by rw [eq_dist_iff] refine ⟨ϖ, b.restrictToLattice, (b.twist hϖ f).restrictToLattice, f, hϖ, hf, ?_, hcast⟩ · intro i simp [Basis.restrictToLattice] rw [this, ← hcast] /-- If `b` is a basis of `Fin 2 → K` and `f₀ ≤ f₁`, the distance of `b.toLattice` and `(b.twist hϖ f).toLattice` is `f₁ - f₀`. -/ lemma dist_twist_monotone (b : Basis (Fin 2) K (Fin 2 → K)) {ϖ : R} (hϖ : Irreducible ϖ) {f : Fin 2 → ℤ} (hf : Monotone f) : dist b.toLattice (R := R) (b.twist hϖ f).toLattice = f 1 - f 0 := by have hcast : f 1 - f 0 = ↑(f 1 - f 0).toNat := (Int.toNat_sub_of_le <| hf (by simp)).symm have : dist b.toLattice (R := R) (b.twist hϖ f).toLattice = (f 1 - f 0).toNat := by rw [eq_dist_iff_monotone] refine ⟨ϖ, b.restrictToLattice, (b.twist hϖ f).restrictToLattice, f, hϖ, hf, ?_, hcast⟩ · intro i simp [Basis.restrictToLattice] rw [this, ← hcast] @[simp] lemma dist_smul_GL_eq_dist (M L : Lattice R) (g : GL (Fin 2) K) : dist (g • M) (g • L) = dist M L := by obtain ⟨ϖ, hϖ, b, f, hf, rfl, rfl, hdiff⟩ := exists_repr_dist' M L rw [← Basis.smulGL_toLattice, ← Basis.smulGL_toLattice, Basis.smulGL_twist] rw [← Nat.cast_inj (R := ℤ), dist_twist _ _ hf, dist_twist _ _ hf] lemma dist_twist₂ (b : Basis (Fin 2) K (Fin 2 → K)) {ϖ : R} (hϖ : Irreducible ϖ) (n m : ℤ) : dist b.toLattice (R := R) (b.twist₂ hϖ n m).toLattice = |n - m| := by simp only [Basis.twist₂] symm by_cases h : m ≤ n · rw [dist_twist, abs_eq_self] · omega · intro i j hij aesop · rw [dist_twist_monotone] · conv_rhs => rw [← neg_sub] rw [abs_eq_neg_self] omega · intro i j hij aesop (add unsafe le_of_lt) lemma dist_ntwist₂ (b : Basis (Fin 2) K (Fin 2 → K)) {ϖ : R} (hϖ : Irreducible ϖ) (n : ℕ) : dist (b.toLattice (R := R)) (b.ntwist₂ hϖ n 0).toLattice = n := by simp [Basis.ntwist₂, ← Nat.cast_inj (R := ℤ), dist_twist₂] /-- If vertices `x` and `y` have distance `n + 1`, there exists a vertex `o` with `inv o x = 1` and `inv y o = n`. This is the inductive step for showing that the Bruhat-Tits graph is connected (see `BruhatTits.reachable`). -/ lemma exists_intermediate_vertex (n : ℕ) (x y : Vertices R) (h : inv x y = n + 1) : ∃ (o : Vertices R), inv y o = n ∧ inv o x = 1 := by obtain ⟨ϖ, hϖ, M', L', bM, bL, rfl, rfl, h0, h1⟩ := exists_repr_inv x y rw [h] at h0 let bT := bM.fromLattice.ntwist₂ hϖ 1 0 let T : Lattice R := bT.toLattice let bT' : Basis (Fin 2) R T.M := bT.restrictToLattice refine ⟨⟦T⟧, ?_, ?_⟩ · rw [inv_mk, dist_symm, eq_dist_iff₂] refine ⟨ϖ, bT', bL, n, 0, hϖ, by simp, ?_, ?_, ?_⟩ · simp only [h0, bT', bT] rw [Basis.restrictToLattice_apply, Basis.ntwist₂_apply₀, Basis.fromLattice_apply, pow_add, ← smul_smul, Subring.smul_def, Subring.coe_pow, zpow_natCast] · simp only [Fin.isValue, h1, zpow_zero, one_smul, bT', bT, T, Basis.restrictToLattice_apply] simp [Basis.ntwist₂_apply₁, Basis.fromLattice_apply] · simp · show dist T M' = 1 rw [dist_symm, eq_dist_iff₂] refine ⟨ϖ, bM, bT', 1, 0, hϖ, by simp, ?_, ?_, ?_⟩ · simp only [bT', bT] rw [Basis.restrictToLattice_apply, Basis.ntwist₂_apply₀, Basis.fromLattice_apply, Subring.smul_def, Subring.coe_pow, zpow_one, pow_one] · rw [Basis.restrictToLattice_apply] simp [bT', bT, Basis.ntwist₂_apply₁, Basis.fromLattice_apply] · simp /-- If two lattices have distance zero, they are equal up to a unit. -/ lemma isSimilar_of_dist_eq_zero {M L : Lattice R} (h : dist M L = 0) : Lattice.IsSimilar R M L := by obtain ⟨ϖ, hϖ, b, f, _, hM, hL, hdiff⟩ := exists_repr_dist' M L subst hM hL simp only [h, Fin.isValue, CharP.cast_eq_zero] at hdiff have hϖ' : ϖ.val ≠ 0 := by simpa using hϖ.ne_zero use (Units.mk0 ϖ.val hϖ') ^ f 0 apply Lattice.ext simp only [Fin.isValue, Lattice.smul_module, Basis.toLattice_module, Basis.smul_toSubmodule] apply congr_arg ext i : 1 have h : f 0 = f 1 := Int.eq_of_sub_eq_zero hdiff simp only [Fin.isValue, Basis.smul'_apply, Units.smul_def, Units.val_zpow_eq_zpow_val, Units.val_mk0, Basis.twist_apply] match i with | 0 => rfl | 1 => rw [h] /-- Two vertices are equal if and only if their distance is zero. -/ lemma eq_iff (M L : Vertices R) : M = L ↔ inv M L = 0 := by constructor · rintro rfl exact inv_self M · refine Quotient.inductionOn₂' M L (fun M L ↦ ?_) intro h simp only [inv_mk] at h apply Quotient.sound exact isSimilar_of_dist_eq_zero h end BruhatTits