l3lab/ntp-mathlib huggingface dataset:
/-- This lemma exists to support the definition `RootSystem.mk'` and usually should not be used
directly. The lemma `RootPairing.coroot_eq_coreflection_of_root_eq_of_span_eq_top` or even
`RootSystem.coroot_eq_coreflection_of_root_eq` will usually be more convenient. -/
lemma coroot_eq_coreflection_of_root_eq_of_span_eq_top' [CharZero R] [NoZeroSMulDivisors R M]
    (p : PerfectPairing R M N)
    (root : ι ↪ M)
    (coroot : ι ↪ N)
    (hp : ∀ i, p.toLin (root i) (coroot i) = 2)
    (hs : ∀ i, MapsTo (preReflection (root i) (p.toLin.flip (coroot i))) (range root) (range root))
    (hsp : span R (range root) = ⊤)
    {i j k : ι} (hk : root k = preReflection (root i) (p.toLin.flip (coroot i)) (root j)) :
    coroot k = preReflection (coroot i) (p.toLin (root i)) (coroot j) := by
  set α := root i
  set β := root j
  set α' := coroot i
  set β' := coroot j
  set sα := preReflection α (p.toLin.flip α')
  set sβ := preReflection β (p.toLin.flip β')
  let sα' := preReflection α' (p.toLin α)
  have hij : preReflection (sα β) (p.toLin.flip (sα' β')) = sα ∘ₗ sβ ∘ₗ sα := by
    ext
    have hpi : (p.toLin.flip (coroot i)) (root i) = 2 := by rw [LinearMap.flip_apply, hp i]
    simp [← preReflection_preReflection β (p.toLin.flip β') hpi, preReflection_apply]
  have hk₀ : root k ≠ 0 := fun h ↦ by simpa [h] using hp k
  apply p.bijectiveRight.injective
  apply Dual.eq_of_preReflection_mapsTo hk₀ (finite_range root) hsp (hp k) (hs k)
  · simp [hk, preReflection_apply, hp i, hp j, mul_two, mul_comm (p.toLin α β')]
  · rw [hk, hij]
    

Proof state:
case a.hg₂
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootPairing ι R M N
i✝ : ι
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
p : PerfectPairing R M N
root : ι ↪ M
coroot : ι ↪ N
hp : ∀ (i : ι), (p.toLin (root i)) (coroot i) = 2
hs : ∀ (i : ι), MapsTo (⇑(preReflection (root i) ((LinearMap.flip p.toLin) (coroot i)))) (range ⇑root) (range ⇑root)
hsp : span R (range ⇑root) = ⊤
i j k : ι
α : M := root i
β : M := root j
α' : N := coroot i
β' : N := coroot j
sα : End R M := preReflection α ((LinearMap.flip p.toLin) α')
hk : root k = sα β
sβ : End R M := preReflection β ((LinearMap.flip p.toLin) β')
sα' : End R N := preReflection α' (p.toLin α)
hij : preReflection (sα β) ((LinearMap.flip p.toLin) (sα' β')) = sα ∘ₗ sβ ∘ₗ sα
hk₀ : root k ≠ 0
⊢ MapsTo (⇑(sα ∘ₗ sβ ∘ₗ sα)) (range ⇑root) (range ⇑root)

Next tactic:
exact (hs i).comp <| (hs j).comp (hs i)
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
⊢ P₁ = P₂

Next tactic:
suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
⊢ P₁ = P₂

Next tactic:
have h₁ := this P₁ P₂ he hr
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
h₁ : range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
⊢ P₁ = P₂

Next tactic:
have h₂ := this P₂ P₁ he.symm hr.symm
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
h₁ : range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
h₂ : range ⇑P₂.coroot ⊆ range ⇑P₁.coroot
⊢ P₁ = P₂

Next tactic:
cases' P₁ with P₁
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    

Proof state:
case mk
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₂ : RootSystem ι R M N
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
P₁ : RootPairing ι R M N
span_eq_top✝ : span R (range ⇑P₁.root) = ⊤
he : { toRootPairing := P₁, span_eq_top := span_eq_top✝ }.toRootPairing.toPerfectPairing.toLin = P₂.toLin
hr : { toRootPairing := P₁, span_eq_top := span_eq_top✝ }.toRootPairing.root = P₂.root
h₁ : range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝ }.toRootPairing.coroot ⊆ range ⇑P₂.coroot
h₂ : range ⇑P₂.coroot ⊆ range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝ }.toRootPairing.coroot
⊢ { toRootPairing := P₁, span_eq_top := span_eq_top✝ } = P₂

Next tactic:
cases' P₂ with P₂
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    

Proof state:
case mk.mk
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
P₁ : RootPairing ι R M N
span_eq_top✝¹ : span R (range ⇑P₁.root) = ⊤
P₂ : RootPairing ι R M N
span_eq_top✝ : span R (range ⇑P₂.root) = ⊤
he :
  { toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.toPerfectPairing.toLin =
    { toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.toPerfectPairing.toLin
hr :
  { toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.root =
    { toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.root
h₁ :
  range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.coroot ⊆
    range ⇑{ toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.coroot
h₂ :
  range ⇑{ toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.coroot ⊆
    range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.coroot
⊢ { toRootPairing := P₁, span_eq_top := span_eq_top✝¹ } = { toRootPairing := P₂, span_eq_top := span_eq_top✝ }

Next tactic:
congr
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    

Proof state:
case mk.mk.e_toRootPairing
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
this : ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot
P₁ : RootPairing ι R M N
span_eq_top✝¹ : span R (range ⇑P₁.root) = ⊤
P₂ : RootPairing ι R M N
span_eq_top✝ : span R (range ⇑P₂.root) = ⊤
he :
  { toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.toPerfectPairing.toLin =
    { toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.toPerfectPairing.toLin
hr :
  { toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.root =
    { toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.root
h₁ :
  range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.coroot ⊆
    range ⇑{ toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.coroot
h₂ :
  range ⇑{ toRootPairing := P₂, span_eq_top := span_eq_top✝ }.toRootPairing.coroot ⊆
    range ⇑{ toRootPairing := P₁, span_eq_top := span_eq_top✝¹ }.toRootPairing.coroot
⊢ P₁ = P₂

Next tactic:
exact RootPairing.ext he hr (le_antisymm h₁ h₂)
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
⊢ ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot

Next tactic:
clear! P₁ P₂
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
⊢ ∀ (P₁ P₂ : RootSystem ι R M N), P₁.toLin = P₂.toLin → P₁.root = P₂.root → range ⇑P₁.coroot ⊆ range ⇑P₂.coroot

Next tactic:
rintro P₁ P₂ he hr - ⟨i, rfl⟩
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  

Proof state:
case intro
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ P₁.coroot i ∈ range ⇑P₂.coroot

Next tactic:
use i
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  

Proof state:
case h
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ P₂.coroot i = P₁.coroot i

Next tactic:
apply P₁.bijectiveRight.injective
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  apply P₁.bijectiveRight.injective
  

Proof state:
case h.a
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ (LinearMap.flip P₁.toLin) (P₂.coroot i) = (LinearMap.flip P₁.toLin) (P₁.coroot i)

Next tactic:
apply Dual.eq_of_preReflection_mapsTo (P₁.ne_zero i) (finite_range P₁.root) P₁.span_eq_top
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  apply P₁.bijectiveRight.injective
  apply Dual.eq_of_preReflection_mapsTo (P₁.ne_zero i) (finite_range P₁.root) P₁.span_eq_top
  · 

Proof state:
case h.a.hf₁
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ ((LinearMap.flip P₁.toLin) (P₂.coroot i)) (P₁.root i) = 2

Next tactic:
exact hr ▸ he ▸ P₂.coroot_root_two i
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  apply P₁.bijectiveRight.injective
  apply Dual.eq_of_preReflection_mapsTo (P₁.ne_zero i) (finite_range P₁.root) P₁.span_eq_top
  · exact hr ▸ he ▸ P₂.coroot_root_two i
  · 

Proof state:
case h.a.hf₂
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ MapsTo (⇑(preReflection (P₁.root i) ((LinearMap.flip P₁.toLin) (P₂.coroot i)))) (range ⇑P₁.root) (range ⇑P₁.root)

Next tactic:
exact hr ▸ he ▸ P₂.mapsTo_preReflection_root i
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  apply P₁.bijectiveRight.injective
  apply Dual.eq_of_preReflection_mapsTo (P₁.ne_zero i) (finite_range P₁.root) P₁.span_eq_top
  · exact hr ▸ he ▸ P₂.coroot_root_two i
  · exact hr ▸ he ▸ P₂.mapsTo_preReflection_root i
  · 

Proof state:
case h.a.hg₁
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ ((LinearMap.flip P₁.toLin) (P₁.coroot i)) (P₁.root i) = 2

Next tactic:
exact P₁.coroot_root_two i
/-- In characteristic zero if there is no torsion, a root system is determined entirely by its
roots. -/
@[ext]
protected lemma ext [CharZero R] [NoZeroSMulDivisors R M]
    {P₁ P₂ : RootSystem ι R M N}
    (he : P₁.toLin = P₂.toLin)
    (hr : P₁.root = P₂.root) :
    P₁ = P₂ := by
  suffices ∀ P₁ P₂ : RootSystem ι R M N, P₁.toLin = P₂.toLin → P₁.root = P₂.root →
      range P₁.coroot ⊆ range P₂.coroot by
    have h₁ := this P₁ P₂ he hr
    have h₂ := this P₂ P₁ he.symm hr.symm
    cases' P₁ with P₁
    cases' P₂ with P₂
    congr
    exact RootPairing.ext he hr (le_antisymm h₁ h₂)
  clear! P₁ P₂
  rintro P₁ P₂ he hr - ⟨i, rfl⟩
  use i
  apply P₁.bijectiveRight.injective
  apply Dual.eq_of_preReflection_mapsTo (P₁.ne_zero i) (finite_range P₁.root) P₁.span_eq_top
  · exact hr ▸ he ▸ P₂.coroot_root_two i
  · exact hr ▸ he ▸ P₂.mapsTo_preReflection_root i
  · exact P₁.coroot_root_two i
  · 

Proof state:
case h.a.hg₂
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
P₁ P₂ : RootSystem ι R M N
he : P₁.toLin = P₂.toLin
hr : P₁.root = P₂.root
i : ι
⊢ MapsTo (⇑(preReflection (P₁.root i) ((LinearMap.flip P₁.toLin) (P₁.coroot i)))) (range ⇑P₁.root) (range ⇑P₁.root)

Next tactic:
exact P₁.mapsTo_preReflection_root i
/-- In characteristic zero if there is no torsion, to check that a family of roots form a root
system, we do not need to check that the coroots are stable under reflections since this follows
from the corresponding property for the roots. -/
def mk' [CharZero R] [NoZeroSMulDivisors R M]
    (p : PerfectPairing R M N)
    (root : ι ↪ M)
    (coroot : ι ↪ N)
    (hp : ∀ i, p.toLin (root i) (coroot i) = 2)
    (hs : ∀ i, MapsTo (preReflection (root i) (p.toLin.flip (coroot i))) (range root) (range root))
    (hsp : span R (range root) = ⊤) :
    RootSystem ι R M N where
  toPerfectPairing := p
  root := root
  coroot := coroot
  root_coroot_two := hp
  mapsTo_preReflection_root := hs
  span_eq_top := hsp
  mapsTo_preReflection_coroot := by
    

Proof state:
ι : Type u_1
R : Type u_2
M : Type u_3
N : Type u_4
inst✝⁷ : _root_.Finite ι
inst✝⁶ : CommRing R
inst✝⁵ : AddCommGroup M
inst✝⁴ : Module R M
inst✝³ : AddCommGroup N
inst✝² : Module R N
P : RootSystem ι R M N
inst✝¹ : CharZero R
inst✝ : NoZeroSMulDivisors R M
p : PerfectPairing R M N
root : ι ↪ M
coroot : ι ↪ N
hp : ∀ (i : ι), (p.toLin (root i)) (coroot i) = 2
hs : ∀ (i : ι), MapsTo (⇑(preReflection (root i) ((LinearMap.flip p.toLin) (coroot i)))) (range ⇑root) (range ⇑root)
hsp : span R (range ⇑root) = ⊤
⊢ ∀ (i : ι), MapsTo (⇑(preReflection (coroot i) (p.toLin (root i)))) (range ⇑coroot) (range ⇑coroot)

Next tactic:
rintro i - ⟨j, rfl⟩