l3lab/ntp-mathlib huggingface dataset:
instance : CanonicallyOrderedAddCommMonoid (Π₀ i, α i) :=
  { (inferInstance : OrderBot (DFinsupp α)),
    (inferInstance : OrderedAddCommMonoid (DFinsupp α)) with
    exists_add_of_le := by
      intro f g h
      exists g - f
      ext i
      

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
inst✝² : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝¹ : (i : ι) → Sub (α i)
inst✝ : ∀ (i : ι), OrderedSub (α i)
f✝ g✝ : Π₀ (i : ι), α i
i✝ : ι
a b : α i✝
src✝¹ : OrderBot (DFinsupp α) := inferInstance
src✝ : OrderedAddCommMonoid (DFinsupp α) := inferInstance
f g : Π₀ (i : ι), α i
h : f ≤ g
i : ι
⊢ g i = (f + (g - f)) i

Next tactic:
exact (add_tsub_cancel_of_le <| h i).symm
@[simp]
theorem single_tsub : single i (a - b) = single i a - single i b := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝³ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝² : (i : ι) → Sub (α i)
inst✝¹ : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝ : DecidableEq ι
⊢ single i (a - b) = single i a - single i b

Next tactic:
ext j
@[simp]
theorem single_tsub : single i (a - b) = single i a - single i b := by
  ext j
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
inst✝³ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝² : (i : ι) → Sub (α i)
inst✝¹ : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝ : DecidableEq ι
j : ι
⊢ (single i (a - b)) j = (single i a - single i b) j

Next tactic:
obtain rfl | h := eq_or_ne i j
@[simp]
theorem single_tsub : single i (a - b) = single i a - single i b := by
  ext j
  obtain rfl | h := eq_or_ne i j
  · 

Proof state:
case h.inl
ι : Type u_1
α : ι → Type u_2
inst✝³ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝² : (i : ι) → Sub (α i)
inst✝¹ : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝ : DecidableEq ι
⊢ (single i (a - b)) i = (single i a - single i b) i

Next tactic:
rw [tsub_apply, single_eq_same, single_eq_same, single_eq_same]
@[simp]
theorem single_tsub : single i (a - b) = single i a - single i b := by
  ext j
  obtain rfl | h := eq_or_ne i j
  · rw [tsub_apply, single_eq_same, single_eq_same, single_eq_same]
  · 

Proof state:
case h.inr
ι : Type u_1
α : ι → Type u_2
inst✝³ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝² : (i : ι) → Sub (α i)
inst✝¹ : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝ : DecidableEq ι
j : ι
h : i ≠ j
⊢ (single i (a - b)) j = (single i a - single i b) j

Next tactic:
rw [tsub_apply, single_eq_of_ne h, single_eq_of_ne h, single_eq_of_ne h, tsub_self]
theorem support_tsub : (f - g).support ⊆ f.support := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝⁴ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝³ : (i : ι) → Sub (α i)
inst✝² : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → (x : α i) → Decidable (x ≠ 0)
⊢ support (f - g) ⊆ support f

Next tactic:
simp (config := { contextual := true }) only [subset_iff, tsub_eq_zero_iff_le, mem_support_iff,
    Ne.def, coe_tsub, Pi.sub_apply, not_imp_not, zero_le, imp_true_iff]
theorem subset_support_tsub : f.support \ g.support ⊆ (f - g).support := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝⁴ : (i : ι) → CanonicallyOrderedAddCommMonoid (α i)
inst✝³ : (i : ι) → Sub (α i)
inst✝² : ∀ (i : ι), OrderedSub (α i)
f g : Π₀ (i : ι), α i
i : ι
a b : α i
inst✝¹ : DecidableEq ι
inst✝ : (i : ι) → (x : α i) → Decidable (x ≠ 0)
⊢ support f \ support g ⊆ support (f - g)

Next tactic:
simp (config := { contextual := true }) [subset_iff]
@[simp]
theorem support_inf : (f ⊓ g).support = f.support ∩ g.support := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
⊢ support (f ⊓ g) = support f ∩ support g

Next tactic:
ext
@[simp]
theorem support_inf : (f ⊓ g).support = f.support ∩ g.support := by
  ext
  

Proof state:
case a
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
a✝ : ι
⊢ a✝ ∈ support (f ⊓ g) ↔ a✝ ∈ support f ∩ support g

Next tactic:
simp only [inf_apply, mem_support_iff, Ne.def, Finset.mem_inter]
@[simp]
theorem support_inf : (f ⊓ g).support = f.support ∩ g.support := by
  ext
  simp only [inf_apply, mem_support_iff, Ne.def, Finset.mem_inter]
  

Proof state:
case a
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
a✝ : ι
⊢ ¬f a✝ ⊓ g a✝ = 0 ↔ ¬f a✝ = 0 ∧ ¬g a✝ = 0

Next tactic:
simp only [inf_eq_min, ← nonpos_iff_eq_zero, min_le_iff, not_or]
@[simp]
theorem support_sup : (f ⊔ g).support = f.support ∪ g.support := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
⊢ support (f ⊔ g) = support f ∪ support g

Next tactic:
ext
@[simp]
theorem support_sup : (f ⊔ g).support = f.support ∪ g.support := by
  ext
  

Proof state:
case a
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
a✝ : ι
⊢ a✝ ∈ support (f ⊔ g) ↔ a✝ ∈ support f ∪ support g

Next tactic:
simp only [Finset.mem_union, mem_support_iff, sup_apply, Ne.def, ← bot_eq_zero]
@[simp]
theorem support_sup : (f ⊔ g).support = f.support ∪ g.support := by
  ext
  simp only [Finset.mem_union, mem_support_iff, sup_apply, Ne.def, ← bot_eq_zero]
  

Proof state:
case a
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
a✝ : ι
⊢ ¬f a✝ ⊔ g a✝ = ⊥ ↔ ¬f a✝ = ⊥ ∨ ¬g a✝ = ⊥

Next tactic:
rw [_root_.sup_eq_bot_iff, not_and_or]
nonrec theorem disjoint_iff : Disjoint f g ↔ Disjoint f.support g.support := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
⊢ Disjoint f g ↔ Disjoint (support f) (support g)

Next tactic:
rw [disjoint_iff, disjoint_iff, DFinsupp.bot_eq_zero, ← DFinsupp.support_eq_empty,
    DFinsupp.support_inf]
nonrec theorem disjoint_iff : Disjoint f g ↔ Disjoint f.support g.support := by
  rw [disjoint_iff, disjoint_iff, DFinsupp.bot_eq_zero, ← DFinsupp.support_eq_empty,
    DFinsupp.support_inf]
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝¹ : (i : ι) → CanonicallyLinearOrderedAddCommMonoid (α i)
inst✝ : DecidableEq ι
f g : Π₀ (i : ι), α i
⊢ support f ∩ support g = ∅ ↔ support f ⊓ support g = ⊥

Next tactic:
rfl
/-- The composition of maps which preserve multiplication, also preserves multiplication. -/
@[to_additive "The composition of addition preserving maps also preserves addition"]
theorem comp {f : α → β} {g : β → γ} (hf : IsMulHom f) (hg : IsMulHom g) : IsMulHom (g ∘ f) :=
  { map_mul := fun x y => by 

Proof state:
α : Type u
β : Type v
inst✝² : Mul α
inst✝¹ : Mul β
γ : Type u_1
inst✝ : Mul γ
f : α → β
g : β → γ
hf : IsMulHom f
hg : IsMulHom g
x y : α
⊢ (g ∘ f) (x * y) = (g ∘ f) x * (g ∘ f) y

Next tactic:
simp only [Function.comp, hf.map_mul, hg.map_mul]
/-- A product of maps which preserve multiplication,
preserves multiplication when the target is commutative. -/
@[to_additive
      "A sum of maps which preserves addition, preserves addition when the target
      is commutative."]
theorem mul {α β} [Semigroup α] [CommSemigroup β] {f g : α → β} (hf : IsMulHom f)
    (hg : IsMulHom g) : IsMulHom fun a => f a * g a :=
  { map_mul := fun a b => by
      

Proof state:
α✝ : Type u
β✝ : Type v
inst✝⁴ : Mul α✝
inst✝³ : Mul β✝
γ : Type u_1
inst✝² : Mul γ
α : Type u_2
β : Type u_3
inst✝¹ : Semigroup α
inst✝ : CommSemigroup β
f g : α → β
hf : IsMulHom f
hg : IsMulHom g
a b : α
⊢ f (a * b) * g (a * b) = f a * g a * (f b * g b)

Next tactic:
simp only [hf.map_mul, hg.map_mul, mul_comm, mul_assoc, mul_left_comm]
/-- A map to a group preserving multiplication is a monoid homomorphism. -/
@[to_additive "A map to an additive group preserving addition is an additive monoid
homomorphism."]
theorem IsMulHom.to_isMonoidHom [MulOneClass α] [Group β] {f : α → β} (hf : IsMulHom f) :
    IsMonoidHom f :=
  { map_one := mul_right_eq_self.1 <| by 

Proof state:
α : Type u
β : Type v
inst✝¹ : MulOneClass α
inst✝ : Group β
f : α → β
hf : IsMulHom f
⊢ ?m.14521 hf * f 1 = ?m.14521 hf

Next tactic:
rw [← hf.map_mul, one_mul]
/-- The composite of two monoid homomorphisms is a monoid homomorphism. -/
@[to_additive
      "The composite of two additive monoid homomorphisms is an additive monoid
      homomorphism."]
theorem comp (hf : IsMonoidHom f) {γ} [MulOneClass γ] {g : β → γ} (hg : IsMonoidHom g) :
    IsMonoidHom (g ∘ f) :=
  { IsMulHom.comp hf.toIsMulHom hg.toIsMulHom with
    map_one := show g _ = 1 by 

Proof state:
α : Type u
β : Type v
inst✝² : MulOneClass α
inst✝¹ : MulOneClass β
f : α → β
hf : IsMonoidHom f
γ : Type u_1
inst✝ : MulOneClass γ
g : β → γ
hg : IsMonoidHom g
src✝ : IsMulHom (g ∘ f) := IsMulHom.comp hf.toIsMulHom hg.toIsMulHom
⊢ g (f 1) = 1

Next tactic:
rw [hf.map_one, hg.map_one]
/-- A group homomorphism sends inverses to inverses. -/
@[to_additive "An additive group homomorphism sends negations to negations."]
theorem map_inv (hf : IsGroupHom f) (a : α) : f a⁻¹ = (f a)⁻¹ :=
  eq_inv_of_mul_eq_one_left <| by 

Proof state:
α : Type u
β : Type v
inst✝¹ : Group α
inst✝ : Group β
f : α → β
hf✝ hf : IsGroupHom f
a : α
⊢ f a⁻¹ * f a = 1

Next tactic:
rw [← hf.map_mul, inv_mul_self, hf.map_one]
@[to_additive]
theorem map_div (hf : IsGroupHom f) (a b : α) : f (a / b) = f a / f b := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : Group α
inst✝ : Group β
f : α → β
hf✝ hf : IsGroupHom f
a b : α
⊢ f (a / b) = f a / f b

Next tactic:
simp_rw [div_eq_mul_inv, hf.map_mul, hf.map_inv]
/-- A group homomorphism is injective iff its kernel is trivial. -/
@[to_additive "An additive group homomorphism is injective if its kernel is trivial."]
theorem injective_iff {f : α → β} (hf : IsGroupHom f) :
    Function.Injective f ↔ ∀ a, f a = 1 → a = 1 :=
  ⟨fun h _ => by 

Proof state:
α : Type u
β : Type v
inst✝¹ : Group α
inst✝ : Group β
f✝ : α → β
hf✝ : IsGroupHom f✝
f : α → β
hf : IsGroupHom f
h : Function.Injective f
x✝ : α
⊢ f x✝ = 1 → x✝ = 1

Next tactic:
rw [← hf.map_one]
/-- A group homomorphism is injective iff its kernel is trivial. -/
@[to_additive "An additive group homomorphism is injective if its kernel is trivial."]
theorem injective_iff {f : α → β} (hf : IsGroupHom f) :
    Function.Injective f ↔ ∀ a, f a = 1 → a = 1 :=
  ⟨fun h _ => by rw [← hf.map_one]; 

Proof state:
α : Type u
β : Type v
inst✝¹ : Group α
inst✝ : Group β
f✝ : α → β
hf✝ : IsGroupHom f✝
f : α → β
hf : IsGroupHom f
h : Function.Injective f
x✝ : α
⊢ f x✝ = f 1 → x✝ = 1

Next tactic:
exact @h _ _
/-- A group homomorphism is injective iff its kernel is trivial. -/
@[to_additive "An additive group homomorphism is injective if its kernel is trivial."]
theorem injective_iff {f : α → β} (hf : IsGroupHom f) :
    Function.Injective f ↔ ∀ a, f a = 1 → a = 1 :=
  ⟨fun h _ => by rw [← hf.map_one]; exact @h _ _, fun h x y hxy =>
    eq_of_div_eq_one <| h _ <| by 

Proof state:
α : Type u
β : Type v
inst✝¹ : Group α
inst✝ : Group β
f✝ : α → β
hf✝ : IsGroupHom f✝
f : α → β
hf : IsGroupHom f
h : ∀ (a : α), f a = 1 → a = 1
x y : α
hxy : f x = f y
⊢ f (x / y) = 1

Next tactic:
rwa [hf.map_div, div_eq_one]
/-- The difference of two additive group homomorphisms is an additive group
homomorphism if the target is commutative. -/
theorem IsAddGroupHom.sub {α β} [AddGroup α] [AddCommGroup β] {f g : α → β} (hf : IsAddGroupHom f)
    (hg : IsAddGroupHom g) : IsAddGroupHom fun a => f a - g a := by
  

Proof state:
α✝ : Type u
β✝ : Type v
α : Type u_1
β : Type u_2
inst✝¹ : AddGroup α
inst✝ : AddCommGroup β
f g : α → β
hf : IsAddGroupHom f
hg : IsAddGroupHom g
⊢ IsAddGroupHom fun a => f a - g a

Next tactic:
simpa only [sub_eq_add_neg] using hf.add hg.neg
@[ext] theorem types_ext {α β : Type u} (f g : α ⟶ β) (h : ∀ a : α, f a = g a) : f = g := by
  

Proof state:
α β : Type u
f g : α ⟶ β
h : ∀ (a : α), f a = g a
⊢ f = g

Next tactic:
funext x
@[ext] theorem types_ext {α β : Type u} (f g : α ⟶ β) (h : ∀ a : α, f a = g a) : f = g := by
  funext x
  

Proof state:
case h
α β : Type u
f g : α ⟶ β
h : ∀ (a : α), f a = g a
x : α
⊢ f x = g x

Next tactic:
exact h x
example [IsIso (↾f)] : Mono (↾f) := by 

Proof state:
α β γ : Type u
f : α → β
g : β → γ
inst✝ : IsIso (↾f)
⊢ Mono (↾f)

Next tactic:
infer_instance
example [IsIso (↾f)] : ↾f ≫ inv (↾f) = 𝟙 α := by 

Proof state:
α β γ : Type u
f : α → β
g : β → γ
inst✝ : IsIso (↾f)
⊢ ↾f ≫ inv (↾f) = 𝟙 α

Next tactic:
simp
/-- The functor which sends a functor to types to its sections. -/
@[simps]
def sectionsFunctor : (J ⥤ Type w) ⥤ Type max u w where
  obj F := F.sections
  map {F G} φ x := ⟨fun j => φ.app j (x.1 j), fun {j j'} f =>
    (congr_fun (φ.naturality f) (x.1 j)).symm.trans (by 

Proof state:
J : Type u
inst✝ : Category.{v, u} J
F G : J ⥤ Type w
φ : F ⟶ G
x : (fun F => ↑(sections F)) F
j j' : J
f : j ⟶ j'
⊢ (F.map f ≫ φ.app j') (↑x j) = (fun j => φ.app j (↑x j)) j'

Next tactic:
simp [x.2 f]
@[simp]
theorem map_comp_apply (f : X ⟶ Y) (g : Y ⟶ Z) (a : F.obj X) :
    (F.map (f ≫ g)) a = (F.map g) ((F.map f) a) := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
F G H : C ⥤ Type w
X Y Z : C
σ : F ⟶ G
τ : G ⟶ H
f : X ⟶ Y
g : Y ⟶ Z
a : F.obj X
⊢ F.map (f ≫ g) a = F.map g (F.map f a)

Next tactic:
simp [types_comp]
@[simp]
theorem map_id_apply (a : F.obj X) : (F.map (𝟙 X)) a = a := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
F G H : C ⥤ Type w
X Y Z : C
σ : F ⟶ G
τ : G ⟶ H
a : F.obj X
⊢ F.map (𝟙 X) a = a

Next tactic:
simp [types_id]
theorem homOfElement_eq_iff {X : Type u} (x y : X) : homOfElement x = homOfElement y ↔ x = y :=
  ⟨fun H => congr_fun H PUnit.unit, by 

Proof state:
X : Type u
x y : X
⊢ x = y → homOfElement x = homOfElement y

Next tactic:
aesop
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  

Proof state:
X Y : Type u
f : X ⟶ Y
⊢ Mono f ↔ Function.Injective f

Next tactic:
constructor
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · 

Proof state:
case mp
X Y : Type u
f : X ⟶ Y
⊢ Mono f → Function.Injective f

Next tactic:
intro H x x' h
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro H x x' h
    

Proof state:
case mp
X Y : Type u
f : X ⟶ Y
H : Mono f
x x' : X
h : f x = f x'
⊢ x = x'

Next tactic:
skip
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro H x x' h
    skip
    

Proof state:
case mp
X Y : Type u
f : X ⟶ Y
H : Mono f
x x' : X
h : f x = f x'
⊢ x = x'

Next tactic:
rw [← homOfElement_eq_iff] at h ⊢
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro H x x' h
    skip
    rw [← homOfElement_eq_iff] at h ⊢
    

Proof state:
case mp
X Y : Type u
f : X ⟶ Y
H : Mono f
x x' : X
h : homOfElement (f x) = homOfElement (f x')
⊢ homOfElement x = homOfElement x'

Next tactic:
exact (cancel_mono f).mp h
/-- A morphism in `Type` is a monomorphism if and only if it is injective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem mono_iff_injective {X Y : Type u} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro H x x' h
    skip
    rw [← homOfElement_eq_iff] at h ⊢
    exact (cancel_mono f).mp h
  · 

Proof state:
case mpr
X Y : Type u
f : X ⟶ Y
⊢ Function.Injective f → Mono f

Next tactic:
exact fun H => ⟨fun g g' h => H.comp_left h⟩
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  

Proof state:
X Y : Type u
f : X ⟶ Y
⊢ Epi f ↔ Function.Surjective f

Next tactic:
constructor
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · 

Proof state:
case mp
X Y : Type u
f : X ⟶ Y
⊢ Epi f → Function.Surjective f

Next tactic:
rintro ⟨H⟩
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    

Proof state:
case mp.mk
X Y : Type u
f : X ⟶ Y
H : ∀ {Z : Type u} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h
⊢ Function.Surjective f

Next tactic:
refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
    

Proof state:
case mp.mk
X Y : Type u
f : X ⟶ Y
H : ∀ {Z : Type u} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h
g₁ g₂ : Y → Prop
hg : g₁ ∘ f = g₂ ∘ f
⊢ g₁ = g₂

Next tactic:
rw [← Equiv.ulift.symm.injective.comp_left.eq_iff]
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
    rw [← Equiv.ulift.symm.injective.comp_left.eq_iff]
    

Proof state:
case mp.mk
X Y : Type u
f : X ⟶ Y
H : ∀ {Z : Type u} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h
g₁ g₂ : Y → Prop
hg : g₁ ∘ f = g₂ ∘ f
⊢ ⇑Equiv.ulift.symm ∘ g₁ = ⇑Equiv.ulift.symm ∘ g₂

Next tactic:
apply H
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
    rw [← Equiv.ulift.symm.injective.comp_left.eq_iff]
    apply H
    

Proof state:
case mp.mk.a
X Y : Type u
f : X ⟶ Y
H : ∀ {Z : Type u} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h
g₁ g₂ : Y → Prop
hg : g₁ ∘ f = g₂ ∘ f
⊢ f ≫ ⇑Equiv.ulift.symm ∘ g₁ = f ≫ ⇑Equiv.ulift.symm ∘ g₂

Next tactic:
change ULift.up ∘ g₁ ∘ f = ULift.up ∘ g₂ ∘ f
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
    rw [← Equiv.ulift.symm.injective.comp_left.eq_iff]
    apply H
    change ULift.up ∘ g₁ ∘ f = ULift.up ∘ g₂ ∘ f
    

Proof state:
case mp.mk.a
X Y : Type u
f : X ⟶ Y
H : ∀ {Z : Type u} (g h : Y ⟶ Z), f ≫ g = f ≫ h → g = h
g₁ g₂ : Y → Prop
hg : g₁ ∘ f = g₂ ∘ f
⊢ ULift.up ∘ g₁ ∘ f = ULift.up ∘ g₂ ∘ f

Next tactic:
rw [hg]
/-- A morphism in `Type` is an epimorphism if and only if it is surjective.

See <https://stacks.math.columbia.edu/tag/003C>.
-/
theorem epi_iff_surjective {X Y : Type u} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · rintro ⟨H⟩
    refine' Function.surjective_of_right_cancellable_Prop fun g₁ g₂ hg => _
    rw [← Equiv.ulift.symm.injective.comp_left.eq_iff]
    apply H
    change ULift.up ∘ g₁ ∘ f = ULift.up ∘ g₂ ∘ f
    rw [hg]
  · 

Proof state:
case mpr
X Y : Type u
f : X ⟶ Y
⊢ Function.Surjective f → Epi f

Next tactic:
exact fun H => ⟨fun g g' h => H.injective_comp_right h⟩
/-- `ofTypeFunctor m` converts from Lean's `Type`-based `Category` to `CategoryTheory`. This
allows us to use these functors in category theory. -/
def ofTypeFunctor (m : Type u → Type v) [_root_.Functor m] [LawfulFunctor m] : Type u ⥤ Type v
    where
  obj := m
  map f := Functor.map f
  map_id := fun α => by 

Proof state:
m : Type u → Type v
inst✝¹ : _root_.Functor m
inst✝ : LawfulFunctor m
α : Type u
⊢ { obj := m, map := fun {X Y} f => Functor.map f }.map (𝟙 α) =
    𝟙 ({ obj := m, map := fun {X Y} f => Functor.map f }.obj α)

Next tactic:
funext X
/-- `ofTypeFunctor m` converts from Lean's `Type`-based `Category` to `CategoryTheory`. This
allows us to use these functors in category theory. -/
def ofTypeFunctor (m : Type u → Type v) [_root_.Functor m] [LawfulFunctor m] : Type u ⥤ Type v
    where
  obj := m
  map f := Functor.map f
  map_id := fun α => by funext X; 

Proof state:
case h
m : Type u → Type v
inst✝¹ : _root_.Functor m
inst✝ : LawfulFunctor m
α : Type u
X : { obj := m, map := fun {X Y} f => Functor.map f }.obj α
⊢ { obj := m, map := fun {X Y} f => Functor.map f }.map (𝟙 α) X =
    𝟙 ({ obj := m, map := fun {X Y} f => Functor.map f }.obj α) X

Next tactic:
apply id_map
theorem zero_pow_le_one : ∀ n : ℕ, (0 : R) ^ n ≤ 1
  | 0 => (pow_zero _).le
  | n + 1 => by
    

Proof state:
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
n✝ m n : ℕ
⊢ 0 ^ (n + 1) ≤ 1

Next tactic:
rw [zero_pow n.succ_pos]
theorem zero_pow_le_one : ∀ n : ℕ, (0 : R) ^ n ≤ 1
  | 0 => (pow_zero _).le
  | n + 1 => by
    rw [zero_pow n.succ_pos]
    

Proof state:
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
n✝ m n : ℕ
⊢ 0 ≤ 1

Next tactic:
exact zero_le_one
theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by
  

Proof state:
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
n m : ℕ
hx : 0 ≤ x
hy : 0 ≤ y
hn : n ≠ 0
⊢ x ^ n + y ^ n ≤ (x + y) ^ n

Next tactic:
rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩
theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by
  rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩
  

Proof state:
case intro
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
m : ℕ
hx : 0 ≤ x
hy : 0 ≤ y
k : ℕ
hn : Nat.succ k ≠ 0
⊢ x ^ Nat.succ k + y ^ Nat.succ k ≤ (x + y) ^ Nat.succ k

Next tactic:
induction' k with k ih
theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by
  rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩
  induction' k with k ih;
  · 

Proof state:
case intro.zero
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
m : ℕ
hx : 0 ≤ x
hy : 0 ≤ y
hn : Nat.succ Nat.zero ≠ 0
⊢ x ^ Nat.succ Nat.zero + y ^ Nat.succ Nat.zero ≤ (x + y) ^ Nat.succ Nat.zero

Next tactic:
have eqn : Nat.succ Nat.zero = 1 := rfl
theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by
  rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩
  induction' k with k ih;
  · have eqn : Nat.succ Nat.zero = 1 := rfl
    

Proof state:
case intro.zero
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
m : ℕ
hx : 0 ≤ x
hy : 0 ≤ y
hn : Nat.succ Nat.zero ≠ 0
eqn : Nat.succ Nat.zero = 1
⊢ x ^ Nat.succ Nat.zero + y ^ Nat.succ Nat.zero ≤ (x + y) ^ Nat.succ Nat.zero

Next tactic:
rw [eqn]
theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by
  rcases Nat.exists_eq_succ_of_ne_zero hn with ⟨k, rfl⟩
  induction' k with k ih;
  · have eqn : Nat.succ Nat.zero = 1 := rfl
    rw [eqn]
    

Proof state:
case intro.zero
M : Type u_1
R : Type u_2
inst✝ : OrderedSemiring R
a x y : R
m : ℕ
hx : 0 ≤ x
hy : 0 ≤ y
hn : Nat.succ Nat.zero ≠ 0
eqn : Nat.succ Nat.zero = 1
⊢ x ^ 1 + y ^ 1 ≤ (x + y) ^ 1

Next tactic:
simp only [pow_one, le_refl]