l3lab/ntp-mathlib huggingface dataset:
theorem StrongEpi.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongEpi f] : StrongEpi g :=
  { epi := by
      rw [Arrow.iso_w' e]
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongEpi f
⊢ Epi (e.inv.left ≫ f ≫ e.hom.right)

Next tactic:
haveI := epi_comp f e.hom.right
theorem StrongEpi.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongEpi f] : StrongEpi g :=
  { epi := by
      rw [Arrow.iso_w' e]
      haveI := epi_comp f e.hom.right
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongEpi f
this : Epi (f ≫ e.hom.right)
⊢ Epi (e.inv.left ≫ f ≫ e.hom.right)

Next tactic:
apply epi_comp
theorem StrongEpi.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongEpi f] : StrongEpi g :=
  { epi := by
      rw [Arrow.iso_w' e]
      haveI := epi_comp f e.hom.right
      apply epi_comp
    llp := fun {X Y} z => by
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongEpi f
X Y : C
z : X ⟶ Y
⊢ ∀ [inst : Mono z], HasLiftingProperty g z

Next tactic:
intro
theorem StrongEpi.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongEpi f] : StrongEpi g :=
  { epi := by
      rw [Arrow.iso_w' e]
      haveI := epi_comp f e.hom.right
      apply epi_comp
    llp := fun {X Y} z => by
      intro
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongEpi f
X Y : C
z : X ⟶ Y
inst✝ : Mono z
⊢ HasLiftingProperty g z

Next tactic:
apply HasLiftingProperty.of_arrow_iso_left e z
theorem StrongMono.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongMono f] : StrongMono g :=
  { mono := by
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongMono f
⊢ Mono g

Next tactic:
rw [Arrow.iso_w' e]
theorem StrongMono.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongMono f] : StrongMono g :=
  { mono := by
      rw [Arrow.iso_w' e]
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongMono f
⊢ Mono (e.inv.left ≫ f ≫ e.hom.right)

Next tactic:
haveI := mono_comp f e.hom.right
theorem StrongMono.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongMono f] : StrongMono g :=
  { mono := by
      rw [Arrow.iso_w' e]
      haveI := mono_comp f e.hom.right
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongMono f
this : Mono (f ≫ e.hom.right)
⊢ Mono (e.inv.left ≫ f ≫ e.hom.right)

Next tactic:
apply mono_comp
theorem StrongMono.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongMono f] : StrongMono g :=
  { mono := by
      rw [Arrow.iso_w' e]
      haveI := mono_comp f e.hom.right
      apply mono_comp
    rlp := fun {X Y} z => by
      

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongMono f
X Y : C
z : X ⟶ Y
⊢ ∀ [inst : Epi z], HasLiftingProperty z g

Next tactic:
intro
theorem StrongMono.of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) [h : StrongMono f] : StrongMono g :=
  { mono := by
      rw [Arrow.iso_w' e]
      haveI := mono_comp f e.hom.right
      apply mono_comp
    rlp := fun {X Y} z => by
      intro
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
h : StrongMono f
X Y : C
z : X ⟶ Y
inst✝ : Epi z
⊢ HasLiftingProperty z g

Next tactic:
apply HasLiftingProperty.of_arrow_iso_right z e
theorem StrongEpi.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongEpi f ↔ StrongEpi g := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongEpi f ↔ StrongEpi g

Next tactic:
constructor
theorem StrongEpi.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongEpi f ↔ StrongEpi g := by
  constructor <;> 

Proof state:
case mp
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongEpi f → StrongEpi g

Next tactic:
intro
theorem StrongEpi.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongEpi f ↔ StrongEpi g := by
  constructor <;> 

Proof state:
case mpr
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongEpi g → StrongEpi f

Next tactic:
intro
theorem StrongEpi.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongEpi f ↔ StrongEpi g := by
  constructor <;> intro
  

Proof state:
case mp
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
a✝ : StrongEpi f
⊢ StrongEpi g
case mpr
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
a✝ : StrongEpi g
⊢ StrongEpi f

Next tactic:
exacts [StrongEpi.of_arrow_iso e, StrongEpi.of_arrow_iso e.symm]
theorem StrongMono.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongMono f ↔ StrongMono g := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongMono f ↔ StrongMono g

Next tactic:
constructor
theorem StrongMono.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongMono f ↔ StrongMono g := by
  constructor <;> 

Proof state:
case mp
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongMono f → StrongMono g

Next tactic:
intro
theorem StrongMono.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongMono f ↔ StrongMono g := by
  constructor <;> 

Proof state:
case mpr
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
⊢ StrongMono g → StrongMono f

Next tactic:
intro
theorem StrongMono.iff_of_arrow_iso {A B A' B' : C} {f : A ⟶ B} {g : A' ⟶ B'}
    (e : Arrow.mk f ≅ Arrow.mk g) : StrongMono f ↔ StrongMono g := by
  constructor <;> intro
  

Proof state:
case mp
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
a✝ : StrongMono f
⊢ StrongMono g
case mpr
C : Type u
inst✝ : Category.{v, u} C
P Q R : C
f✝ : P ⟶ Q
g✝ : Q ⟶ R
A B A' B' : C
f : A ⟶ B
g : A' ⟶ B'
e : Arrow.mk f ≅ Arrow.mk g
a✝ : StrongMono g
⊢ StrongMono f

Next tactic:
exacts [StrongMono.of_arrow_iso e, StrongMono.of_arrow_iso e.symm]
/-- A strong epimorphism that is a monomorphism is an isomorphism. -/
theorem isIso_of_mono_of_strongEpi (f : P ⟶ Q) [Mono f] [StrongEpi f] : IsIso f :=
  ⟨⟨(CommSq.mk (show 𝟙 P ≫ f = f ≫ 𝟙 Q by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
P Q : C
f : P ⟶ Q
inst✝¹ : Mono f
inst✝ : StrongEpi f
⊢ 𝟙 P ≫ f = f ≫ 𝟙 Q

Next tactic:
simp
/-- A strong epimorphism that is a monomorphism is an isomorphism. -/
theorem isIso_of_mono_of_strongEpi (f : P ⟶ Q) [Mono f] [StrongEpi f] : IsIso f :=
  ⟨⟨(CommSq.mk (show 𝟙 P ≫ f = f ≫ 𝟙 Q by simp)).lift, by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
P Q : C
f : P ⟶ Q
inst✝¹ : Mono f
inst✝ : StrongEpi f
⊢ f ≫ CommSq.lift (_ : CommSq (𝟙 P) f f (𝟙 Q)) = 𝟙 P ∧ CommSq.lift (_ : CommSq (𝟙 P) f f (𝟙 Q)) ≫ f = 𝟙 Q

Next tactic:
aesop_cat
/-- A strong monomorphism that is an epimorphism is an isomorphism. -/
theorem isIso_of_epi_of_strongMono (f : P ⟶ Q) [Epi f] [StrongMono f] : IsIso f :=
  ⟨⟨(CommSq.mk (show 𝟙 P ≫ f = f ≫ 𝟙 Q by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
P Q : C
f : P ⟶ Q
inst✝¹ : Epi f
inst✝ : StrongMono f
⊢ 𝟙 P ≫ f = f ≫ 𝟙 Q

Next tactic:
simp
/-- A strong monomorphism that is an epimorphism is an isomorphism. -/
theorem isIso_of_epi_of_strongMono (f : P ⟶ Q) [Epi f] [StrongMono f] : IsIso f :=
  ⟨⟨(CommSq.mk (show 𝟙 P ≫ f = f ≫ 𝟙 Q by simp)).lift, by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
P Q : C
f : P ⟶ Q
inst✝¹ : Epi f
inst✝ : StrongMono f
⊢ f ≫ CommSq.lift (_ : CommSq (𝟙 P) f f (𝟙 Q)) = 𝟙 P ∧ CommSq.lift (_ : CommSq (𝟙 P) f f (𝟙 Q)) ≫ f = 𝟙 Q

Next tactic:
aesop_cat
/-- All `HasAntidiagonal` instances are equal -/
instance [AddMonoid A] : Subsingleton (HasAntidiagonal A) :=
  ⟨by
    

Proof state:
A : Type u_1
inst✝ : AddMonoid A
⊢ ∀ (a b : HasAntidiagonal A), a = b

Next tactic:
rintro ⟨a, ha⟩ ⟨b, hb⟩
/-- All `HasAntidiagonal` instances are equal -/
instance [AddMonoid A] : Subsingleton (HasAntidiagonal A) :=
  ⟨by
    rintro ⟨a, ha⟩ ⟨b, hb⟩
    

Proof state:
case mk.mk
A : Type u_1
inst✝ : AddMonoid A
a : A → Finset (A × A)
ha : ∀ {n : A} {a_1 : A × A}, a_1 ∈ a n ↔ a_1.1 + a_1.2 = n
b : A → Finset (A × A)
hb : ∀ {n : A} {a : A × A}, a ∈ b n ↔ a.1 + a.2 = n
⊢ { antidiagonal := a, mem_antidiagonal := ha } = { antidiagonal := b, mem_antidiagonal := hb }

Next tactic:
congr with n xy
/-- All `HasAntidiagonal` instances are equal -/
instance [AddMonoid A] : Subsingleton (HasAntidiagonal A) :=
  ⟨by
    rintro ⟨a, ha⟩ ⟨b, hb⟩
    congr with n xy
    

Proof state:
case mk.mk.e_antidiagonal.h.a
A : Type u_1
inst✝ : AddMonoid A
a : A → Finset (A × A)
ha : ∀ {n : A} {a_1 : A × A}, a_1 ∈ a n ↔ a_1.1 + a_1.2 = n
b : A → Finset (A × A)
hb : ∀ {n : A} {a : A × A}, a ∈ b n ↔ a.1 + a.2 = n
n : A
xy : A × A
⊢ xy ∈ a n ↔ xy ∈ b n

Next tactic:
rw [ha, hb]
lemma hasAntidiagonal_congr (A : Type*) [AddMonoid A]
    [H1 : HasAntidiagonal A] [H2 : HasAntidiagonal A] :
    H1.antidiagonal = H2.antidiagonal := by 

Proof state:
A✝ : Type u_1
A : Type u_2
inst✝ : AddMonoid A
H1 H2 : HasAntidiagonal A
⊢ antidiagonal = antidiagonal

Next tactic:
congr!
theorem swap_mem_antidiagonal [AddCommMonoid A] [HasAntidiagonal A] {n : A} {xy : A × A}:
    xy.swap ∈ antidiagonal n ↔ xy ∈ antidiagonal n := by
  

Proof state:
A : Type u_1
inst✝¹ : AddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
xy : A × A
⊢ Prod.swap xy ∈ antidiagonal n ↔ xy ∈ antidiagonal n

Next tactic:
simp [add_comm]
@[simp] theorem map_prodComm_antidiagonal [AddCommMonoid A] [HasAntidiagonal A] {n : A} :
    (antidiagonal n).map (Equiv.prodComm A A) = antidiagonal n :=
  Finset.ext fun ⟨a, b⟩ => by 

Proof state:
A : Type u_1
inst✝¹ : AddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
x✝ : A × A
a b : A
⊢ (a, b) ∈ map (Equiv.toEmbedding (Equiv.prodComm A A)) (antidiagonal n) ↔ (a, b) ∈ antidiagonal n

Next tactic:
simp [add_comm]
/-- A point in the antidiagonal is determined by its first co-ordinate. -/
theorem antidiagonal_congr [AddCancelMonoid A] [HasAntidiagonal A] {n : A} {p q : A × A}
    (hp : p ∈ antidiagonal n) (hq : q ∈ antidiagonal n) : p = q ↔ p.fst = q.fst := by
  

Proof state:
A : Type u_1
inst✝¹ : AddCancelMonoid A
inst✝ : HasAntidiagonal A
n : A
p q : A × A
hp : p ∈ antidiagonal n
hq : q ∈ antidiagonal n
⊢ p = q ↔ p.1 = q.1

Next tactic:
refine' ⟨congr_arg Prod.fst, fun h ↦ Prod.ext h ((add_right_inj q.fst).mp _)⟩
/-- A point in the antidiagonal is determined by its first co-ordinate. -/
theorem antidiagonal_congr [AddCancelMonoid A] [HasAntidiagonal A] {n : A} {p q : A × A}
    (hp : p ∈ antidiagonal n) (hq : q ∈ antidiagonal n) : p = q ↔ p.fst = q.fst := by
  refine' ⟨congr_arg Prod.fst, fun h ↦ Prod.ext h ((add_right_inj q.fst).mp _)⟩
  

Proof state:
A : Type u_1
inst✝¹ : AddCancelMonoid A
inst✝ : HasAntidiagonal A
n : A
p q : A × A
hp : p ∈ antidiagonal n
hq : q ∈ antidiagonal n
h : p.1 = q.1
⊢ q.1 + p.2 = q.1 + q.2

Next tactic:
rw [mem_antidiagonal] at hp hq
/-- A point in the antidiagonal is determined by its first co-ordinate. -/
theorem antidiagonal_congr [AddCancelMonoid A] [HasAntidiagonal A] {n : A} {p q : A × A}
    (hp : p ∈ antidiagonal n) (hq : q ∈ antidiagonal n) : p = q ↔ p.fst = q.fst := by
  refine' ⟨congr_arg Prod.fst, fun h ↦ Prod.ext h ((add_right_inj q.fst).mp _)⟩
  rw [mem_antidiagonal] at hp hq
  

Proof state:
A : Type u_1
inst✝¹ : AddCancelMonoid A
inst✝ : HasAntidiagonal A
n : A
p q : A × A
hp : p.1 + p.2 = n
hq : q.1 + q.2 = n
h : p.1 = q.1
⊢ q.1 + p.2 = q.1 + q.2

Next tactic:
rw [hq, ← h, hp]
@[simp]
theorem antidiagonal_zero : antidiagonal (0 : A) = {(0, 0)} := by
  

Proof state:
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
⊢ antidiagonal 0 = {(0, 0)}

Next tactic:
ext ⟨x, y⟩
@[simp]
theorem antidiagonal_zero : antidiagonal (0 : A) = {(0, 0)} := by
  ext ⟨x, y⟩
  

Proof state:
case a.mk
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
x y : A
⊢ (x, y) ∈ antidiagonal 0 ↔ (x, y) ∈ {(0, 0)}

Next tactic:
simp
theorem antidiagonal.fst_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.1 ≤ n := by
  

Proof state:
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ kl.1 ≤ n

Next tactic:
rw [le_iff_exists_add]
theorem antidiagonal.fst_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.1 ≤ n := by
  rw [le_iff_exists_add]
  

Proof state:
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ ∃ c, n = kl.1 + c

Next tactic:
use kl.2
theorem antidiagonal.fst_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.1 ≤ n := by
  rw [le_iff_exists_add]
  use kl.2
  

Proof state:
case h
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ n = kl.1 + kl.2

Next tactic:
rwa [mem_antidiagonal, eq_comm] at hlk
theorem antidiagonal.snd_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.2 ≤ n := by
  

Proof state:
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ kl.2 ≤ n

Next tactic:
rw [le_iff_exists_add]
theorem antidiagonal.snd_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.2 ≤ n := by
  rw [le_iff_exists_add]
  

Proof state:
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ ∃ c, n = kl.2 + c

Next tactic:
use kl.1
theorem antidiagonal.snd_le {n : A} {kl : A × A} (hlk : kl ∈ antidiagonal n) : kl.2 ≤ n := by
  rw [le_iff_exists_add]
  use kl.1
  

Proof state:
case h
A : Type u_1
inst✝¹ : CanonicallyOrderedAddCommMonoid A
inst✝ : HasAntidiagonal A
n : A
kl : A × A
hlk : kl ∈ antidiagonal n
⊢ n = kl.2 + kl.1

Next tactic:
rwa [mem_antidiagonal, eq_comm, add_comm] at hlk
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  

Proof state:
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n m : A
inst✝¹ : DecidablePred fun x => x = m
inst✝ : Decidable (m ≤ n)
⊢ filter (fun x => x.1 = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅

Next tactic:
ext ⟨a, b⟩
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  

Proof state:
case a.mk
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n m : A
inst✝¹ : DecidablePred fun x => x = m
inst✝ : Decidable (m ≤ n)
a b : A
⊢ (a, b) ∈ filter (fun x => x.1 = m) (antidiagonal n) ↔ (a, b) ∈ if m ≤ n then {(m, n - m)} else ∅

Next tactic:
suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    

Proof state:
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n m : A
inst✝¹ : DecidablePred fun x => x = m
inst✝ : Decidable (m ≤ n)
a b : A
this : a = m → (a + b = n ↔ m ≤ n ∧ b = n - m)
⊢ (a, b) ∈ filter (fun x => x.1 = m) (antidiagonal n) ↔ (a, b) ∈ if m ≤ n then {(m, n - m)} else ∅

Next tactic:
rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    

Proof state:
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n m : A
inst✝¹ : DecidablePred fun x => x = m
inst✝ : Decidable (m ≤ n)
a b : A
this : a = m → (a + b = n ↔ m ≤ n ∧ b = n - m)
⊢ (a, b).1 + (a, b).2 = n ∧ (a, b).1 = m ↔ m ≤ n ∧ a = m ∧ b = n - m ∨ ¬m ≤ n ∧ (a, b) ∈ ∅

Next tactic:
simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  

Proof state:
case a.mk
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n m : A
inst✝¹ : DecidablePred fun x => x = m
inst✝ : Decidable (m ≤ n)
a b : A
⊢ a = m → (a + b = n ↔ m ≤ n ∧ b = n - m)

Next tactic:
rintro rfl
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  rintro rfl
  

Proof state:
case a.mk
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n a b : A
inst✝¹ : DecidablePred fun x => x = a
inst✝ : Decidable (a ≤ n)
⊢ a + b = n ↔ a ≤ n ∧ b = n - a

Next tactic:
constructor
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  rintro rfl
  constructor
  · 

Proof state:
case a.mk.mp
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n a b : A
inst✝¹ : DecidablePred fun x => x = a
inst✝ : Decidable (a ≤ n)
⊢ a + b = n → a ≤ n ∧ b = n - a

Next tactic:
rintro rfl
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  rintro rfl
  constructor
  · rintro rfl
    

Proof state:
case a.mk.mp
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
a b : A
inst✝¹ : DecidablePred fun x => x = a
inst✝ : Decidable (a ≤ a + b)
⊢ a ≤ a + b ∧ b = a + b - a

Next tactic:
exact ⟨le_add_right le_rfl, (add_tsub_cancel_left _ _).symm⟩
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  rintro rfl
  constructor
  · rintro rfl
    exact ⟨le_add_right le_rfl, (add_tsub_cancel_left _ _).symm⟩
  · 

Proof state:
case a.mk.mpr
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n a b : A
inst✝¹ : DecidablePred fun x => x = a
inst✝ : Decidable (a ≤ n)
⊢ a ≤ n ∧ b = n - a → a + b = n

Next tactic:
rintro ⟨h, rfl⟩
theorem filter_fst_eq_antidiagonal (n m : A) [DecidablePred (· = m)] [Decidable (m ≤ n)] :
    filter (fun x : A × A ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
  ext ⟨a, b⟩
  suffices a = m → (a + b = n ↔ m ≤ n ∧ b = n - m) by
    rw [mem_filter, mem_antidiagonal, apply_ite (fun n ↦ (a, b) ∈ n), mem_singleton,
      Prod.mk.inj_iff, ite_prop_iff_or]
    simpa [ ← and_assoc, @and_right_comm _ (a = _), and_congr_left_iff]
  rintro rfl
  constructor
  · rintro rfl
    exact ⟨le_add_right le_rfl, (add_tsub_cancel_left _ _).symm⟩
  · rintro ⟨h, rfl⟩
    

Proof state:
case a.mk.mpr.intro
A : Type u_1
inst✝⁶ : CanonicallyOrderedAddCommMonoid A
inst✝⁵ : Sub A
inst✝⁴ : OrderedSub A
inst✝³ : ContravariantClass A A (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
inst✝² : HasAntidiagonal A
n a : A
inst✝¹ : DecidablePred fun x => x = a
inst✝ : Decidable (a ≤ n)
h : a ≤ n
⊢ a + (n - a) = n

Next tactic:
exact add_tsub_cancel_of_le h