l3lab/ntp-mathlib huggingface dataset:
theorem isUnit_of_associated_mul [CancelCommMonoidWithZero α] {p b : α} (h : Associated (p * b) p)
    (hp : p ≠ 0) : IsUnit b := by
  cases' h with a ha
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p b : α
hp : p ≠ 0
a : αˣ
ha : p * b * ↑a = p
⊢ IsUnit b

Next tactic:
refine' isUnit_of_mul_eq_one b a ((mul_right_inj' hp).mp _)
theorem isUnit_of_associated_mul [CancelCommMonoidWithZero α] {p b : α} (h : Associated (p * b) p)
    (hp : p ≠ 0) : IsUnit b := by
  cases' h with a ha
  refine' isUnit_of_mul_eq_one b a ((mul_right_inj' hp).mp _)
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p b : α
hp : p ≠ 0
a : αˣ
ha : p * b * ↑a = p
⊢ p * (b * ↑a) = p * 1

Next tactic:
rwa [← mul_assoc, mul_one]
theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) :
    ¬Associated p q := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
h : DvdNotUnit p q
⊢ ¬p ~ᵤ q

Next tactic:
rintro ⟨a, rfl⟩
theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) :
    ¬Associated p q := by
  rintro ⟨a, rfl⟩
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
a : αˣ
h : DvdNotUnit p (p * ↑a)
⊢ False

Next tactic:
obtain ⟨hp, x, hx, hx'⟩ := h
theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) :
    ¬Associated p q := by
  rintro ⟨a, rfl⟩
  obtain ⟨hp, x, hx, hx'⟩ := h
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
a : αˣ
hp : p ≠ 0
x : α
hx : ¬IsUnit x
hx' : p * ↑a = p * x
⊢ False

Next tactic:
rcases (mul_right_inj' hp).mp hx' with rfl
theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) :
    ¬Associated p q := by
  rintro ⟨a, rfl⟩
  obtain ⟨hp, x, hx, hx'⟩ := h
  rcases (mul_right_inj' hp).mp hx' with rfl
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
a : αˣ
hp : p ≠ 0
hx : ¬IsUnit ↑a
hx' : p * ↑a = p * ↑a
⊢ False

Next tactic:
exact hx a.isUnit
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
h : DvdNotUnit p q
⊢ p ≠ q

Next tactic:
by_contra hcontra
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  by_contra hcontra
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
h : DvdNotUnit p q
hcontra : p = q
⊢ False

Next tactic:
obtain ⟨hp, x, hx', hx''⟩ := h
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  by_contra hcontra
  obtain ⟨hp, x, hx', hx''⟩ := h
  

Proof state:
case intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
hcontra : p = q
hp : p ≠ 0
x : α
hx' : ¬IsUnit x
hx'' : q = p * x
⊢ False

Next tactic:
conv_lhs at hx'' => rw [← hcontra, ← mul_one p]
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  by_contra hcontra
  obtain ⟨hp, x, hx', hx''⟩ := h
  conv_lhs at hx'' => 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
hcontra : p = q
hp : p ≠ 0
x : α
hx' : ¬IsUnit x
hx'' : q = p * x
| q

Next tactic:
rw [← hcontra, ← mul_one p]
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  by_contra hcontra
  obtain ⟨hp, x, hx', hx''⟩ := h
  conv_lhs at hx'' => rw [← hcontra, ← mul_one p]
  

Proof state:
case intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
hcontra : p = q
hp : p ≠ 0
x : α
hx' : ¬IsUnit x
hx'' : p * 1 = p * x
⊢ False

Next tactic:
rw [(mul_left_cancel₀ hp hx'').symm] at hx'
theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by
  by_contra hcontra
  obtain ⟨hp, x, hx', hx''⟩ := h
  conv_lhs at hx'' => rw [← hcontra, ← mul_one p]
  rw [(mul_left_cancel₀ hp hx'').symm] at hx'
  

Proof state:
case intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
hcontra : p = q
hp : p ≠ 0
x : α
hx' : ¬IsUnit 1
hx'' : p * 1 = p * x
⊢ False

Next tactic:
exact hx' isUnit_one
theorem pow_injective_of_not_unit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q)
    (hq' : q ≠ 0) : Function.Injective fun n : ℕ => q ^ n := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
q : α
hq : ¬IsUnit q
hq' : q ≠ 0
⊢ Function.Injective fun n => q ^ n

Next tactic:
refine' injective_of_lt_imp_ne fun n m h => DvdNotUnit.ne ⟨pow_ne_zero n hq', q ^ (m - n), _, _⟩
theorem pow_injective_of_not_unit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q)
    (hq' : q ≠ 0) : Function.Injective fun n : ℕ => q ^ n := by
  refine' injective_of_lt_imp_ne fun n m h => DvdNotUnit.ne ⟨pow_ne_zero n hq', q ^ (m - n), _, _⟩
  · 

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
q : α
hq : ¬IsUnit q
hq' : q ≠ 0
n m : ℕ
h : n < m
⊢ ¬IsUnit (q ^ (m - n))

Next tactic:
exact not_isUnit_of_not_isUnit_dvd hq (dvd_pow (dvd_refl _) (Nat.sub_pos_of_lt h).ne')
theorem pow_injective_of_not_unit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q)
    (hq' : q ≠ 0) : Function.Injective fun n : ℕ => q ^ n := by
  refine' injective_of_lt_imp_ne fun n m h => DvdNotUnit.ne ⟨pow_ne_zero n hq', q ^ (m - n), _, _⟩
  · exact not_isUnit_of_not_isUnit_dvd hq (dvd_pow (dvd_refl _) (Nat.sub_pos_of_lt h).ne')
  · 

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
q : α
hq : ¬IsUnit q
hq' : q ≠ 0
n m : ℕ
h : n < m
⊢ q ^ m = q ^ n * q ^ (m - n)

Next tactic:
exact (pow_mul_pow_sub q h.le).symm
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p q : α
hp : Prime p
n : ℕ
⊢ q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i

Next tactic:
induction' n with n ih generalizing q
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
q : α
⊢ q ∣ p ^ Nat.zero ↔ ∃ i ≤ Nat.zero, q ~ᵤ p ^ i

Next tactic:
simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
⊢ q ∣ p ^ Nat.succ n ↔ ∃ i ≤ Nat.succ n, q ~ᵤ p ^ i

Next tactic:
refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : q ∣ p ^ Nat.succ n
⊢ ∃ i ≤ Nat.succ n, q ~ᵤ p ^ i

Next tactic:
rw [pow_succ] at h
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : q ∣ p * p ^ n
⊢ ∃ i ≤ Nat.succ n, q ~ᵤ p ^ i

Next tactic:
rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · 

Proof state:
case succ.inl.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : p * q ∣ p * p ^ n
⊢ ∃ i ≤ Nat.succ n, p * q ~ᵤ p ^ i

Next tactic:
rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    

Proof state:
case succ.inl.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : ∃ i ≤ n, q ~ᵤ p ^ i
⊢ ∃ i ≤ Nat.succ n, p * q ~ᵤ p ^ i

Next tactic:
rcases h with ⟨i, hi, hq⟩
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    rcases h with ⟨i, hi, hq⟩
    

Proof state:
case succ.inl.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
i : ℕ
hi : i ≤ n
hq : q ~ᵤ p ^ i
⊢ ∃ i ≤ Nat.succ n, p * q ~ᵤ p ^ i

Next tactic:
refine' ⟨i + 1, Nat.succ_le_succ hi, (hq.mul_left p).trans _⟩
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    rcases h with ⟨i, hi, hq⟩
    refine' ⟨i + 1, Nat.succ_le_succ hi, (hq.mul_left p).trans _⟩
    

Proof state:
case succ.inl.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
i : ℕ
hi : i ≤ n
hq : q ~ᵤ p ^ i
⊢ p * p ^ i ~ᵤ p ^ (i + 1)

Next tactic:
rw [pow_succ]
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    rcases h with ⟨i, hi, hq⟩
    refine' ⟨i + 1, Nat.succ_le_succ hi, (hq.mul_left p).trans _⟩
    rw [pow_succ]
    

Proof state:
case succ.inl.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
i : ℕ
hi : i ≤ n
hq : q ~ᵤ p ^ i
⊢ p * p ^ i ~ᵤ p * p ^ i

Next tactic:
rfl
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    rcases h with ⟨i, hi, hq⟩
    refine' ⟨i + 1, Nat.succ_le_succ hi, (hq.mul_left p).trans _⟩
    rw [pow_succ]
    rfl
  · 

Proof state:
case succ.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : q ∣ p * p ^ n
hno : q ∣ p ^ n
⊢ ∃ i ≤ Nat.succ n, q ~ᵤ p ^ i

Next tactic:
obtain ⟨i, hi, hq⟩ := ih.mp hno
theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) :
    q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by
  induction' n with n ih generalizing q
  · simp [← isUnit_iff_dvd_one, associated_one_iff_isUnit]
  refine' ⟨fun h => _, fun ⟨i, hi, hq⟩ => hq.dvd.trans (pow_dvd_pow p hi)⟩
  rw [pow_succ] at h
  rcases hp.left_dvd_or_dvd_right_of_dvd_mul h with (⟨q, rfl⟩ | hno)
  · rw [mul_dvd_mul_iff_left hp.ne_zero, ih] at h
    rcases h with ⟨i, hi, hq⟩
    refine' ⟨i + 1, Nat.succ_le_succ hi, (hq.mul_left p).trans _⟩
    rw [pow_succ]
    rfl
  · obtain ⟨i, hi, hq⟩ := ih.mp hno
    

Proof state:
case succ.inr.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
n : ℕ
ih : ∀ {q : α}, q ∣ p ^ n ↔ ∃ i ≤ n, q ~ᵤ p ^ i
q : α
h : q ∣ p * p ^ n
hno : q ∣ p ^ n
i : ℕ
hi : i ≤ n
hq : q ~ᵤ p ^ i
⊢ ∃ i ≤ Nat.succ n, q ~ᵤ p ^ i

Next tactic:
exact ⟨i, hi.trans n.le_succ, hq⟩
instance instFunLike : FunLike (PerfectPairing R M N) M (fun _  ↦ N →ₗ[R] R) where
  coe f := f.toLin
  coe_injective' x y h := by 

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup N
inst✝ : Module R N
x y : PerfectPairing R M N
h : (fun f => ⇑f.toLin) x = (fun f => ⇑f.toLin) y
⊢ x = y

Next tactic:
cases x
instance instFunLike : FunLike (PerfectPairing R M N) M (fun _  ↦ N →ₗ[R] R) where
  coe f := f.toLin
  coe_injective' x y h := by cases x; 

Proof state:
case mk
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup N
inst✝ : Module R N
y : PerfectPairing R M N
toLin✝ : M →ₗ[R] N →ₗ[R] R
bijectiveLeft✝ : Bijective ⇑toLin✝
bijectiveRight✝ : Bijective ⇑(LinearMap.flip toLin✝)
h :
  (fun f => ⇑f.toLin) { toLin := toLin✝, bijectiveLeft := bijectiveLeft✝, bijectiveRight := bijectiveRight✝ } =
    (fun f => ⇑f.toLin) y
⊢ { toLin := toLin✝, bijectiveLeft := bijectiveLeft✝, bijectiveRight := bijectiveRight✝ } = y

Next tactic:
cases y
instance instFunLike : FunLike (PerfectPairing R M N) M (fun _  ↦ N →ₗ[R] R) where
  coe f := f.toLin
  coe_injective' x y h := by cases x; cases y; 

Proof state:
case mk.mk
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁴ : CommRing R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup N
inst✝ : Module R N
toLin✝¹ : M →ₗ[R] N →ₗ[R] R
bijectiveLeft✝¹ : Bijective ⇑toLin✝¹
bijectiveRight✝¹ : Bijective ⇑(LinearMap.flip toLin✝¹)
toLin✝ : M →ₗ[R] N →ₗ[R] R
bijectiveLeft✝ : Bijective ⇑toLin✝
bijectiveRight✝ : Bijective ⇑(LinearMap.flip toLin✝)
h :
  (fun f => ⇑f.toLin) { toLin := toLin✝¹, bijectiveLeft := bijectiveLeft✝¹, bijectiveRight := bijectiveRight✝¹ } =
    (fun f => ⇑f.toLin) { toLin := toLin✝, bijectiveLeft := bijectiveLeft✝, bijectiveRight := bijectiveRight✝ }
⊢ { toLin := toLin✝¹, bijectiveLeft := bijectiveLeft✝¹, bijectiveRight := bijectiveRight✝¹ } =
    { toLin := toLin✝, bijectiveLeft := bijectiveLeft✝, bijectiveRight := bijectiveRight✝ }

Next tactic:
simpa using h
lemma trans_dualMap_symm_flip : e.trans e.flip.symm.dualMap = Dual.eval R N := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
⊢ ↑(e ≪≫ₗ dualMap (symm (flip e))) = Dual.eval R N

Next tactic:
ext
lemma trans_dualMap_symm_flip : e.trans e.flip.symm.dualMap = Dual.eval R N := by
  ext; 

Proof state:
case h.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
x✝¹ : N
x✝ : Dual R N
⊢ (↑(e ≪≫ₗ dualMap (symm (flip e))) x✝¹) x✝ = ((Dual.eval R N) x✝¹) x✝

Next tactic:
simp [symm_flip]
/-- If `N` is in perfect pairing with `M`, then it is reflexive. -/
lemma isReflexive_of_equiv_dual_of_isReflexive : IsReflexive R N := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
⊢ IsReflexive R N

Next tactic:
constructor
/-- If `N` is in perfect pairing with `M`, then it is reflexive. -/
lemma isReflexive_of_equiv_dual_of_isReflexive : IsReflexive R N := by
  constructor
  

Proof state:
case bijective_dual_eval'
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
⊢ Bijective ⇑(Dual.eval R N)

Next tactic:
rw [← trans_dualMap_symm_flip e]
/-- If `N` is in perfect pairing with `M`, then it is reflexive. -/
lemma isReflexive_of_equiv_dual_of_isReflexive : IsReflexive R N := by
  constructor
  rw [← trans_dualMap_symm_flip e]
  

Proof state:
case bijective_dual_eval'
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
⊢ Bijective ⇑↑(e ≪≫ₗ dualMap (symm (flip e)))

Next tactic:
exact LinearEquiv.bijective _
@[simp] lemma flip_flip (h : IsReflexive R N := isReflexive_of_equiv_dual_of_isReflexive e) :
    e.flip.flip = e := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
h : optParam (IsReflexive R N) (_ : IsReflexive R N)
⊢ flip (flip e) = e

Next tactic:
ext
@[simp] lemma flip_flip (h : IsReflexive R N := isReflexive_of_equiv_dual_of_isReflexive e) :
    e.flip.flip = e := by
  ext; 

Proof state:
case h.h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
h : optParam (IsReflexive R N) (_ : IsReflexive R N)
x✝¹ : N
x✝ : M
⊢ ((flip (flip e)) x✝¹) x✝ = (e x✝¹) x✝

Next tactic:
rfl
@[simp]
lemma dualCoannihilator_map_linearEquiv_flip (p : Submodule R M) :
    (p.map e.flip).dualCoannihilator = p.dualAnnihilator.map e.symm := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R M
⊢ dualCoannihilator (map (LinearEquiv.flip e) p) = map (LinearEquiv.symm e) (dualAnnihilator p)

Next tactic:
ext
@[simp]
lemma dualCoannihilator_map_linearEquiv_flip (p : Submodule R M) :
    (p.map e.flip).dualCoannihilator = p.dualAnnihilator.map e.symm := by
  ext; 

Proof state:
case h
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R M
x✝ : N
⊢ x✝ ∈ dualCoannihilator (map (LinearEquiv.flip e) p) ↔ x✝ ∈ map (LinearEquiv.symm e) (dualAnnihilator p)

Next tactic:
simp [LinearEquiv.symm_apply_eq, Submodule.mem_dualCoannihilator]
@[simp]
lemma map_dualAnnihilator_linearEquiv_flip_symm (p : Submodule R N) :
    p.dualAnnihilator.map e.flip.symm = (p.map e).dualCoannihilator := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R N
⊢ map (LinearEquiv.symm (LinearEquiv.flip e)) (dualAnnihilator p) = dualCoannihilator (map e p)

Next tactic:
have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive
@[simp]
lemma map_dualAnnihilator_linearEquiv_flip_symm (p : Submodule R N) :
    p.dualAnnihilator.map e.flip.symm = (p.map e).dualCoannihilator := by
  have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R N
this : IsReflexive R N
⊢ map (LinearEquiv.symm (LinearEquiv.flip e)) (dualAnnihilator p) = dualCoannihilator (map e p)

Next tactic:
rw [← dualCoannihilator_map_linearEquiv_flip, flip_flip]
@[simp]
lemma map_dualCoannihilator_linearEquiv_flip (p : Submodule R (Dual R M)) :
    p.dualCoannihilator.map e.flip = (p.map e.symm).dualAnnihilator := by
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R (Dual R M)
⊢ map (LinearEquiv.flip e) (dualCoannihilator p) = dualAnnihilator (map (LinearEquiv.symm e) p)

Next tactic:
have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive
@[simp]
lemma map_dualCoannihilator_linearEquiv_flip (p : Submodule R (Dual R M)) :
    p.dualCoannihilator.map e.flip = (p.map e.symm).dualAnnihilator := by
  have : IsReflexive R N := e.isReflexive_of_equiv_dual_of_isReflexive
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : CommRing R
inst✝⁴ : AddCommGroup M
inst✝³ : Module R M
inst✝² : AddCommGroup N
inst✝¹ : Module R N
inst✝ : IsReflexive R M
e : N ≃ₗ[R] Dual R M
p : Submodule R (Dual R M)
this : IsReflexive R N
⊢ map (LinearEquiv.flip e) (dualCoannihilator p) = dualAnnihilator (map (LinearEquiv.symm e) p)

Next tactic:
suffices (p.map e.symm).dualAnnihilator.map e.flip.symm =
      (p.dualCoannihilator.map e.flip).map e.flip.symm by
    exact (Submodule.map_injective_of_injective e.flip.symm.injective this).symm