l3lab/ntp-mathlib huggingface dataset:
theorem congr_inv_of_congr_hom (F G : C ⥤ D) {X Y : C} (e : X ≅ Y) (hX : F.obj X = G.obj X)
    (hY : F.obj Y = G.obj Y)
    (h₂ : F.map e.hom = eqToHom (by rw [hX]) ≫ G.map e.hom ≫ eqToHom (by rw [hY])) :
    F.map e.inv = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
X Y : C
e : X ≅ Y
hX : F.obj X = G.obj X
hY : F.obj Y = G.obj Y
h₂ : F.map e.hom = eqToHom (_ : F.obj X = G.obj X) ≫ G.map e.hom ≫ eqToHom (_ : G.obj Y = F.obj Y)
⊢ F.obj Y = G.obj Y

Next tactic:
rw [hY]
theorem congr_inv_of_congr_hom (F G : C ⥤ D) {X Y : C} (e : X ≅ Y) (hX : F.obj X = G.obj X)
    (hY : F.obj Y = G.obj Y)
    (h₂ : F.map e.hom = eqToHom (by rw [hX]) ≫ G.map e.hom ≫ eqToHom (by rw [hY])) :
    F.map e.inv = eqToHom (by rw [hY]) ≫ G.map e.inv ≫ eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
X Y : C
e : X ≅ Y
hX : F.obj X = G.obj X
hY : F.obj Y = G.obj Y
h₂ : F.map e.hom = eqToHom (_ : F.obj X = G.obj X) ≫ G.map e.hom ≫ eqToHom (_ : G.obj Y = F.obj Y)
⊢ G.obj X = F.obj X

Next tactic:
rw [hX]
theorem congr_inv_of_congr_hom (F G : C ⥤ D) {X Y : C} (e : X ≅ Y) (hX : F.obj X = G.obj X)
    (hY : F.obj Y = G.obj Y)
    (h₂ : F.map e.hom = eqToHom (by rw [hX]) ≫ G.map e.hom ≫ eqToHom (by rw [hY])) :
    F.map e.inv = eqToHom (by rw [hY]) ≫ G.map e.inv ≫ eqToHom (by rw [hX]) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
X Y : C
e : X ≅ Y
hX : F.obj X = G.obj X
hY : F.obj Y = G.obj Y
h₂ : F.map e.hom = eqToHom (_ : F.obj X = G.obj X) ≫ G.map e.hom ≫ eqToHom (_ : G.obj Y = F.obj Y)
⊢ F.map e.inv = eqToHom (_ : F.obj Y = G.obj Y) ≫ G.map e.inv ≫ eqToHom (_ : G.obj X = F.obj X)

Next tactic:
simp only [← IsIso.Iso.inv_hom e, Functor.map_inv, h₂, IsIso.inv_comp, inv_eqToHom,
    Category.assoc]
theorem congr_map (F : C ⥤ D) {X Y : C} {f g : X ⟶ Y} (h : f = g) : F.map f = F.map g := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y : C
f g : X ⟶ Y
h : f = g
⊢ F.map f = F.map g

Next tactic:
rw [h]
theorem map_comp_heq (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y) (hz : F.obj Z = G.obj Z)
    (hf : HEq (F.map f) (G.map f)) (hg : HEq (F.map g) (G.map g)) :
    HEq (F.map (f ≫ g)) (G.map (f ≫ g)) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
hx : F.obj X = G.obj X
hy : F.obj Y = G.obj Y
hz : F.obj Z = G.obj Z
hf : HEq (F.map f) (G.map f)
hg : HEq (F.map g) (G.map g)
⊢ HEq (F.map (f ≫ g)) (G.map (f ≫ g))

Next tactic:
rw [F.map_comp, G.map_comp]
theorem map_comp_heq (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y) (hz : F.obj Z = G.obj Z)
    (hf : HEq (F.map f) (G.map f)) (hg : HEq (F.map g) (G.map g)) :
    HEq (F.map (f ≫ g)) (G.map (f ≫ g)) := by
  rw [F.map_comp, G.map_comp]
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
hx : F.obj X = G.obj X
hy : F.obj Y = G.obj Y
hz : F.obj Z = G.obj Z
hf : HEq (F.map f) (G.map f)
hg : HEq (F.map g) (G.map g)
⊢ HEq (F.map f ≫ F.map g) (G.map f ≫ G.map g)

Next tactic:
congr
theorem map_comp_heq' (hobj : ∀ X : C, F.obj X = G.obj X)
    (hmap : ∀ {X Y} (f : X ⟶ Y), HEq (F.map f) (G.map f)) :
    HEq (F.map (f ≫ g)) (G.map (f ≫ g)) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
hobj : ∀ (X : C), F.obj X = G.obj X
hmap : ∀ {X Y : C} (f : X ⟶ Y), HEq (F.map f) (G.map f)
⊢ HEq (F.map (f ≫ g)) (G.map (f ≫ g))

Next tactic:
rw [Functor.hext hobj fun _ _ => hmap]
theorem postcomp_map_heq (H : D ⥤ E) (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y)
    (hmap : HEq (F.map f) (G.map f)) : HEq ((F ⋙ H).map f) ((G ⋙ H).map f) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
H : D ⥤ E
hx : F.obj X = G.obj X
hy : F.obj Y = G.obj Y
hmap : HEq (F.map f) (G.map f)
⊢ HEq ((F ⋙ H).map f) ((G ⋙ H).map f)

Next tactic:
dsimp
theorem postcomp_map_heq (H : D ⥤ E) (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y)
    (hmap : HEq (F.map f) (G.map f)) : HEq ((F ⋙ H).map f) ((G ⋙ H).map f) := by
  dsimp
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
H : D ⥤ E
hx : F.obj X = G.obj X
hy : F.obj Y = G.obj Y
hmap : HEq (F.map f) (G.map f)
⊢ HEq (H.map (F.map f)) (H.map (G.map f))

Next tactic:
congr
theorem postcomp_map_heq' (H : D ⥤ E) (hobj : ∀ X : C, F.obj X = G.obj X)
    (hmap : ∀ {X Y} (f : X ⟶ Y), HEq (F.map f) (G.map f)) : HEq ((F ⋙ H).map f) ((G ⋙ H).map f) :=
  by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F G : C ⥤ D
X Y Z : C
f : X ⟶ Y
g : Y ⟶ Z
H : D ⥤ E
hobj : ∀ (X : C), F.obj X = G.obj X
hmap : ∀ {X Y : C} (f : X ⟶ Y), HEq (F.map f) (G.map f)
⊢ HEq ((F ⋙ H).map f) ((G ⋙ H).map f)

Next tactic:
rw [Functor.hext hobj fun _ _ => hmap]
theorem hcongr_hom {F G : C ⥤ D} (h : F = G) {X Y} (f : X ⟶ Y) : HEq (F.map f) (G.map f) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
E : Type u₃
inst✝ : Category.{v₃, u₃} E
F✝ G✝ : C ⥤ D
X✝ Y✝ Z : C
f✝ : X✝ ⟶ Y✝
g : Y✝ ⟶ Z
F G : C ⥤ D
h : F = G
X Y : C
f : X ⟶ Y
⊢ HEq (F.map f) (G.map f)

Next tactic:
rw [h]
/-- This is not always a good idea as a `@[simp]` lemma,
as we lose the ability to use results that interact with `F`,
e.g. the naturality of a natural transformation.

In some files it may be appropriate to use `local attribute [simp] eqToHom_map`, however.
-/
theorem eqToHom_map (F : C ⥤ D) {X Y : C} (p : X = Y) :
    F.map (eqToHom p) = eqToHom (congr_arg F.obj p) := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y : C
p : X = Y
⊢ F.map (eqToHom p) = eqToHom (_ : F.obj X = F.obj Y)

Next tactic:
cases p
/-- This is not always a good idea as a `@[simp]` lemma,
as we lose the ability to use results that interact with `F`,
e.g. the naturality of a natural transformation.

In some files it may be appropriate to use `local attribute [simp] eqToHom_map`, however.
-/
theorem eqToHom_map (F : C ⥤ D) {X Y : C} (p : X = Y) :
    F.map (eqToHom p) = eqToHom (congr_arg F.obj p) := by cases p; 

Proof state:
case refl
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X : C
⊢ F.map (eqToHom (_ : X = X)) = eqToHom (_ : F.obj X = F.obj X)

Next tactic:
simp
/-- See the note on `eqToHom_map` regarding using this as a `simp` lemma.
-/
theorem eqToIso_map (F : C ⥤ D) {X Y : C} (p : X = Y) :
    F.mapIso (eqToIso p) = eqToIso (congr_arg F.obj p) := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y : C
p : X = Y
⊢ F.mapIso (eqToIso p) = eqToIso (_ : F.obj X = F.obj Y)

Next tactic:
ext
/-- See the note on `eqToHom_map` regarding using this as a `simp` lemma.
-/
theorem eqToIso_map (F : C ⥤ D) {X Y : C} (p : X = Y) :
    F.mapIso (eqToIso p) = eqToIso (congr_arg F.obj p) := by ext; 

Proof state:
case w
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y : C
p : X = Y
⊢ (F.mapIso (eqToIso p)).hom = (eqToIso (_ : F.obj X = F.obj Y)).hom

Next tactic:
cases p
/-- See the note on `eqToHom_map` regarding using this as a `simp` lemma.
-/
theorem eqToIso_map (F : C ⥤ D) {X Y : C} (p : X = Y) :
    F.mapIso (eqToIso p) = eqToIso (congr_arg F.obj p) := by ext; cases p; 

Proof state:
case w.refl
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X : C
⊢ (F.mapIso (eqToIso (_ : X = X))).hom = (eqToIso (_ : F.obj X = F.obj X)).hom

Next tactic:
simp
@[simp]
theorem eqToHom_app {F G : C ⥤ D} (h : F = G) (X : C) :
    (eqToHom h : F ⟶ G).app X = eqToHom (Functor.congr_obj h X) := by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
h : F = G
X : C
⊢ (eqToHom h).app X = eqToHom (_ : F.obj X = G.obj X)

Next tactic:
subst h
@[simp]
theorem eqToHom_app {F G : C ⥤ D} (h : F = G) (X : C) :
    (eqToHom h : F ⟶ G).app X = eqToHom (Functor.congr_obj h X) := by subst h; 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X : C
⊢ (eqToHom (_ : F = F)).app X = eqToHom (_ : F.obj X = F.obj X)

Next tactic:
rfl
theorem NatTrans.congr {F G : C ⥤ D} (α : F ⟶ G) {X Y : C} (h : X = Y) :
    α.app X = F.map (eqToHom h) ≫ α.app Y ≫ G.map (eqToHom h.symm) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
α : F ⟶ G
X Y : C
h : X = Y
⊢ α.app X = F.map (eqToHom h) ≫ α.app Y ≫ G.map (eqToHom (_ : Y = X))

Next tactic:
rw [α.naturality_assoc]
theorem NatTrans.congr {F G : C ⥤ D} (α : F ⟶ G) {X Y : C} (h : X = Y) :
    α.app X = F.map (eqToHom h) ≫ α.app Y ≫ G.map (eqToHom h.symm) := by
  rw [α.naturality_assoc]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F G : C ⥤ D
α : F ⟶ G
X Y : C
h : X = Y
⊢ α.app X = α.app X ≫ G.map (eqToHom h) ≫ G.map (eqToHom (_ : Y = X))

Next tactic:
simp [eqToHom_map]
theorem eq_conj_eqToHom {X Y : C} (f : X ⟶ Y) : f = eqToHom rfl ≫ f ≫ eqToHom rfl := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X Y : C
f : X ⟶ Y
⊢ f = eqToHom (_ : X = X) ≫ f ≫ eqToHom (_ : Y = Y)

Next tactic:
simp only [Category.id_comp, eqToHom_refl, Category.comp_id]
theorem dcongr_arg {ι : Type*} {F G : ι → C} (α : ∀ i, F i ⟶ G i) {i j : ι} (h : i = j) :
    α i = eqToHom (congr_arg F h) ≫ α j ≫ eqToHom (congr_arg G h.symm) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
ι : Type u_1
F G : ι → C
α : (i : ι) → F i ⟶ G i
i j : ι
h : i = j
⊢ α i = eqToHom (_ : F i = F j) ≫ α j ≫ eqToHom (_ : G j = G i)

Next tactic:
subst h
theorem dcongr_arg {ι : Type*} {F G : ι → C} (α : ∀ i, F i ⟶ G i) {i j : ι} (h : i = j) :
    α i = eqToHom (congr_arg F h) ≫ α j ≫ eqToHom (congr_arg G h.symm) := by
  subst h
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
ι : Type u_1
F G : ι → C
α : (i : ι) → F i ⟶ G i
i : ι
⊢ α i = eqToHom (_ : F i = F i) ≫ α i ≫ eqToHom (_ : G i = G i)

Next tactic:
simp
theorem sign_of_neg {r : ℝ} (hr : r < 0) : sign r = -1 := by 

Proof state:
r : ℝ
hr : r < 0
⊢ sign r = -1

Next tactic:
rw [sign, if_pos hr]
theorem sign_of_pos {r : ℝ} (hr : 0 < r) : sign r = 1 := by 

Proof state:
r : ℝ
hr : 0 < r
⊢ sign r = 1

Next tactic:
rw [sign, if_pos hr, if_neg hr.not_lt]
@[simp]
theorem sign_zero : sign 0 = 0 := by 

Proof state:
⊢ sign 0 = 0

Next tactic:
rw [sign, if_neg (lt_irrefl _), if_neg (lt_irrefl _)]
@[simp]
theorem sign_one : sign 1 = 1 :=
  sign_of_pos <| by 

Proof state:
⊢ 0 < 1

Next tactic:
norm_num
theorem sign_apply_eq (r : ℝ) : sign r = -1 ∨ sign r = 0 ∨ sign r = 1 := by
  

Proof state:
r : ℝ
⊢ sign r = -1 ∨ sign r = 0 ∨ sign r = 1

Next tactic:
obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
theorem sign_apply_eq (r : ℝ) : sign r = -1 ∨ sign r = 0 ∨ sign r = 1 := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · 

Proof state:
case inl
r : ℝ
hn : r < 0
⊢ sign r = -1 ∨ sign r = 0 ∨ sign r = 1

Next tactic:
exact Or.inl <| sign_of_neg hn
theorem sign_apply_eq (r : ℝ) : sign r = -1 ∨ sign r = 0 ∨ sign r = 1 := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · exact Or.inl <| sign_of_neg hn
  · 

Proof state:
case inr.inl
⊢ sign 0 = -1 ∨ sign 0 = 0 ∨ sign 0 = 1

Next tactic:
exact Or.inr <| Or.inl <| sign_zero
theorem sign_apply_eq (r : ℝ) : sign r = -1 ∨ sign r = 0 ∨ sign r = 1 := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · exact Or.inl <| sign_of_neg hn
  · exact Or.inr <| Or.inl <| sign_zero
  · 

Proof state:
case inr.inr
r : ℝ
hp : 0 < r
⊢ sign r = -1 ∨ sign r = 0 ∨ sign r = 1

Next tactic:
exact Or.inr <| Or.inr <| sign_of_pos hp
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  

Proof state:
r : ℝ
⊢ sign r = 0 ↔ r = 0

Next tactic:
refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  

Proof state:
r : ℝ
h : sign r = 0
⊢ r = 0

Next tactic:
obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · 

Proof state:
case inl
r : ℝ
h : sign r = 0
hn : r < 0
⊢ r = 0

Next tactic:
rw [sign_of_neg hn, neg_eq_zero] at h
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, neg_eq_zero] at h
    

Proof state:
case inl
r : ℝ
h : 1 = 0
hn : r < 0
⊢ r = 0

Next tactic:
exact (one_ne_zero h).elim
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, neg_eq_zero] at h
    exact (one_ne_zero h).elim
  · 

Proof state:
case inr.inl
h : sign 0 = 0
⊢ 0 = 0

Next tactic:
rfl
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, neg_eq_zero] at h
    exact (one_ne_zero h).elim
  · rfl
  · 

Proof state:
case inr.inr
r : ℝ
h : sign r = 0
hp : 0 < r
⊢ r = 0

Next tactic:
rw [sign_of_pos hp] at h
@[simp]
theorem sign_eq_zero_iff {r : ℝ} : sign r = 0 ↔ r = 0 := by
  refine' ⟨fun h => _, fun h => h.symm ▸ sign_zero⟩
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, neg_eq_zero] at h
    exact (one_ne_zero h).elim
  · rfl
  · rw [sign_of_pos hp] at h
    

Proof state:
case inr.inr
r : ℝ
h : 1 = 0
hp : 0 < r
⊢ r = 0

Next tactic:
exact (one_ne_zero h).elim
theorem sign_int_cast (z : ℤ) : sign (z : ℝ) = ↑(Int.sign z) := by
  

Proof state:
z : ℤ
⊢ sign ↑z = ↑(Int.sign z)

Next tactic:
obtain hn | rfl | hp := lt_trichotomy z (0 : ℤ)
theorem sign_int_cast (z : ℤ) : sign (z : ℝ) = ↑(Int.sign z) := by
  obtain hn | rfl | hp := lt_trichotomy z (0 : ℤ)
  · 

Proof state:
case inl
z : ℤ
hn : z < 0
⊢ sign ↑z = ↑(Int.sign z)

Next tactic:
rw [sign_of_neg (Int.cast_lt_zero.mpr hn), Int.sign_eq_neg_one_of_neg hn, Int.cast_neg,
      Int.cast_one]
theorem sign_int_cast (z : ℤ) : sign (z : ℝ) = ↑(Int.sign z) := by
  obtain hn | rfl | hp := lt_trichotomy z (0 : ℤ)
  · rw [sign_of_neg (Int.cast_lt_zero.mpr hn), Int.sign_eq_neg_one_of_neg hn, Int.cast_neg,
      Int.cast_one]
  · 

Proof state:
case inr.inl
⊢ sign ↑0 = ↑(Int.sign 0)

Next tactic:
rw [Int.cast_zero, sign_zero, Int.sign_zero, Int.cast_zero]
theorem sign_int_cast (z : ℤ) : sign (z : ℝ) = ↑(Int.sign z) := by
  obtain hn | rfl | hp := lt_trichotomy z (0 : ℤ)
  · rw [sign_of_neg (Int.cast_lt_zero.mpr hn), Int.sign_eq_neg_one_of_neg hn, Int.cast_neg,
      Int.cast_one]
  · rw [Int.cast_zero, sign_zero, Int.sign_zero, Int.cast_zero]
  · 

Proof state:
case inr.inr
z : ℤ
hp : 0 < z
⊢ sign ↑z = ↑(Int.sign z)

Next tactic:
rw [sign_of_pos (Int.cast_pos.mpr hp), Int.sign_eq_one_of_pos hp, Int.cast_one]
theorem sign_neg {r : ℝ} : sign (-r) = -sign r := by
  

Proof state:
r : ℝ
⊢ sign (-r) = -sign r

Next tactic:
obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
theorem sign_neg {r : ℝ} : sign (-r) = -sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · 

Proof state:
case inl
r : ℝ
hn : r < 0
⊢ sign (-r) = -sign r

Next tactic:
rw [sign_of_neg hn, sign_of_pos (neg_pos.mpr hn), neg_neg]
theorem sign_neg {r : ℝ} : sign (-r) = -sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, sign_of_pos (neg_pos.mpr hn), neg_neg]
  · 

Proof state:
case inr.inl
⊢ sign (-0) = -sign 0

Next tactic:
rw [sign_zero, neg_zero, sign_zero]
theorem sign_neg {r : ℝ} : sign (-r) = -sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, sign_of_pos (neg_pos.mpr hn), neg_neg]
  · rw [sign_zero, neg_zero, sign_zero]
  · 

Proof state:
case inr.inr
r : ℝ
hp : 0 < r
⊢ sign (-r) = -sign r

Next tactic:
rw [sign_of_pos hp, sign_of_neg (neg_lt_zero.mpr hp)]
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  

Proof state:
r : ℝ
⊢ 0 ≤ sign r * r

Next tactic:
obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · 

Proof state:
case inl
r : ℝ
hn : r < 0
⊢ 0 ≤ sign r * r

Next tactic:
rw [sign_of_neg hn]
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn]
    

Proof state:
case inl
r : ℝ
hn : r < 0
⊢ 0 ≤ -1 * r

Next tactic:
exact mul_nonneg_of_nonpos_of_nonpos (by norm_num) hn.le
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn]
    exact mul_nonneg_of_nonpos_of_nonpos (by 

Proof state:
r : ℝ
hn : r < 0
⊢ -1 ≤ 0

Next tactic:
norm_num
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn]
    exact mul_nonneg_of_nonpos_of_nonpos (by norm_num) hn.le
  · 

Proof state:
case inr.inl
⊢ 0 ≤ sign 0 * 0

Next tactic:
rw [mul_zero]
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn]
    exact mul_nonneg_of_nonpos_of_nonpos (by norm_num) hn.le
  · rw [mul_zero]
  · 

Proof state:
case inr.inr
r : ℝ
hp : 0 < r
⊢ 0 ≤ sign r * r

Next tactic:
rw [sign_of_pos hp, one_mul]
theorem sign_mul_nonneg (r : ℝ) : 0 ≤ sign r * r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn]
    exact mul_nonneg_of_nonpos_of_nonpos (by norm_num) hn.le
  · rw [mul_zero]
  · rw [sign_of_pos hp, one_mul]
    

Proof state:
case inr.inr
r : ℝ
hp : 0 < r
⊢ 0 ≤ r

Next tactic:
exact hp.le
theorem sign_mul_pos_of_ne_zero (r : ℝ) (hr : r ≠ 0) : 0 < sign r * r := by
  

Proof state:
r : ℝ
hr : r ≠ 0
⊢ 0 < sign r * r

Next tactic:
refine' lt_of_le_of_ne (sign_mul_nonneg r) fun h => hr _
theorem sign_mul_pos_of_ne_zero (r : ℝ) (hr : r ≠ 0) : 0 < sign r * r := by
  refine' lt_of_le_of_ne (sign_mul_nonneg r) fun h => hr _
  

Proof state:
r : ℝ
hr : r ≠ 0
h : 0 = sign r * r
⊢ r = 0

Next tactic:
have hs0 := (zero_eq_mul.mp h).resolve_right hr
theorem sign_mul_pos_of_ne_zero (r : ℝ) (hr : r ≠ 0) : 0 < sign r * r := by
  refine' lt_of_le_of_ne (sign_mul_nonneg r) fun h => hr _
  have hs0 := (zero_eq_mul.mp h).resolve_right hr
  

Proof state:
r : ℝ
hr : r ≠ 0
h : 0 = sign r * r
hs0 : sign r = 0
⊢ r = 0

Next tactic:
exact sign_eq_zero_iff.mp hs0
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  

Proof state:
r : ℝ
⊢ (sign r)⁻¹ = sign r

Next tactic:
obtain hn | hz | hp := sign_apply_eq r
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · 

Proof state:
case inl
r : ℝ
hn : sign r = -1
⊢ (sign r)⁻¹ = sign r

Next tactic:
rw [hn]
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · rw [hn]
    

Proof state:
case inl
r : ℝ
hn : sign r = -1
⊢ (-1)⁻¹ = -1

Next tactic:
norm_num
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · rw [hn]
    norm_num
  · 

Proof state:
case inr.inl
r : ℝ
hz : sign r = 0
⊢ (sign r)⁻¹ = sign r

Next tactic:
rw [hz]
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · rw [hn]
    norm_num
  · rw [hz]
    

Proof state:
case inr.inl
r : ℝ
hz : sign r = 0
⊢ 0⁻¹ = 0

Next tactic:
exact inv_zero
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · rw [hn]
    norm_num
  · rw [hz]
    exact inv_zero
  · 

Proof state:
case inr.inr
r : ℝ
hp : sign r = 1
⊢ (sign r)⁻¹ = sign r

Next tactic:
rw [hp]
@[simp]
theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by
  obtain hn | hz | hp := sign_apply_eq r
  · rw [hn]
    norm_num
  · rw [hz]
    exact inv_zero
  · rw [hp]
    

Proof state:
case inr.inr
r : ℝ
hp : sign r = 1
⊢ 1⁻¹ = 1

Next tactic:
exact inv_one
@[simp]
theorem sign_inv (r : ℝ) : sign r⁻¹ = sign r := by
  

Proof state:
r : ℝ
⊢ sign r⁻¹ = sign r

Next tactic:
obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
@[simp]
theorem sign_inv (r : ℝ) : sign r⁻¹ = sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · 

Proof state:
case inl
r : ℝ
hn : r < 0
⊢ sign r⁻¹ = sign r

Next tactic:
rw [sign_of_neg hn, sign_of_neg (inv_lt_zero.mpr hn)]
@[simp]
theorem sign_inv (r : ℝ) : sign r⁻¹ = sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, sign_of_neg (inv_lt_zero.mpr hn)]
  · 

Proof state:
case inr.inl
⊢ sign 0⁻¹ = sign 0

Next tactic:
rw [sign_zero, inv_zero, sign_zero]
@[simp]
theorem sign_inv (r : ℝ) : sign r⁻¹ = sign r := by
  obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ)
  · rw [sign_of_neg hn, sign_of_neg (inv_lt_zero.mpr hn)]
  · rw [sign_zero, inv_zero, sign_zero]
  · 

Proof state:
case inr.inr
r : ℝ
hp : 0 < r
⊢ sign r⁻¹ = sign r

Next tactic:
rw [sign_of_pos hp, sign_of_pos (inv_pos.mpr hp)]
theorem IsMatching.toEdge_eq_of_adj {M : Subgraph G} (h : M.IsMatching) {v w : V} (hv : v ∈ M.verts)
    (hvw : M.Adj v w) : h.toEdge ⟨v, hv⟩ = ⟨⟦(v, w)⟧, hvw⟩ := by
  

Proof state:
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
v w : V
hv : v ∈ M.verts
hvw : Adj M v w
⊢ toEdge h { val := v, property := hv } = { val := ⟦(v, w)⟧, property := hvw }

Next tactic:
simp only [IsMatching.toEdge, Subtype.mk_eq_mk]
theorem IsMatching.toEdge_eq_of_adj {M : Subgraph G} (h : M.IsMatching) {v w : V} (hv : v ∈ M.verts)
    (hvw : M.Adj v w) : h.toEdge ⟨v, hv⟩ = ⟨⟦(v, w)⟧, hvw⟩ := by
  simp only [IsMatching.toEdge, Subtype.mk_eq_mk]
  

Proof state:
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
v w : V
hv : v ∈ M.verts
hvw : Adj M v w
⊢ ⟦(v, Exists.choose (_ : ∃! w, Adj M (↑{ val := v, property := hv }) w))⟧ = ⟦(v, w)⟧

Next tactic:
congr
theorem IsMatching.toEdge_eq_of_adj {M : Subgraph G} (h : M.IsMatching) {v w : V} (hv : v ∈ M.verts)
    (hvw : M.Adj v w) : h.toEdge ⟨v, hv⟩ = ⟨⟦(v, w)⟧, hvw⟩ := by
  simp only [IsMatching.toEdge, Subtype.mk_eq_mk]
  congr
  

Proof state:
case e_a.e_snd
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
v w : V
hv : v ∈ M.verts
hvw : Adj M v w
⊢ Exists.choose (_ : ∃! w, Adj M (↑{ val := v, property := hv }) w) = w

Next tactic:
exact ((h (M.edge_vert hvw)).choose_spec.2 w hvw).symm
theorem IsMatching.toEdge.surjective {M : Subgraph G} (h : M.IsMatching) :
    Function.Surjective h.toEdge := by
  

Proof state:
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
⊢ Function.Surjective (toEdge h)

Next tactic:
rintro ⟨e, he⟩
theorem IsMatching.toEdge.surjective {M : Subgraph G} (h : M.IsMatching) :
    Function.Surjective h.toEdge := by
  rintro ⟨e, he⟩
  

Proof state:
case mk
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
e : Sym2 V
he : e ∈ edgeSet M
⊢ ∃ a, toEdge h a = { val := e, property := he }

Next tactic:
refine Sym2.ind (fun x y he => ?_) e he
theorem IsMatching.toEdge.surjective {M : Subgraph G} (h : M.IsMatching) :
    Function.Surjective h.toEdge := by
  rintro ⟨e, he⟩
  refine Sym2.ind (fun x y he => ?_) e he
  

Proof state:
case mk
V : Type u
G : SimpleGraph V
M✝ M : Subgraph G
h : IsMatching M
e : Sym2 V
he✝ : e ∈ edgeSet M
x y : V
he : ⟦(x, y)⟧ ∈ edgeSet M
⊢ ∃ a, toEdge h a = { val := ⟦(x, y)⟧, property := he }

Next tactic:
exact ⟨⟨x, M.edge_vert he⟩, h.toEdge_eq_of_adj _ he⟩