l3lab/ntp-mathlib huggingface dataset:
/-- The special case of Graham's conjecture where all numbers are squarefree. -/
lemma grahamConjecture_of_squarefree {n : ℕ} (f : ℕ → ℕ) (hf' : ∀ k < n, Squarefree (f k)) :
    GrahamConjecture n f := by
  rintro hn hf
  by_contra!
  set 𝒜 := (Iio n).image fun n ↦ primeFactors (f n)
  have hf'' : ∀ i < n, ∀ j, Squarefree (f i / (f i).gcd (f j)) :=
    fun i hi j ↦ (hf' _ hi).squarefree_of_dvd $ div_dvd_of_dvd $ gcd_dvd_left _ _
  refine lt_irrefl n ?_
  calc
    n = 𝒜.card := ?_
    _ ≤ (𝒜 \\ 𝒜).card := 𝒜.card_le_card_diffs
    _ ≤ (Ioo 0 n).card := card_le_card_of_inj_on (fun s ↦ ∏ p in s, p) ?_ ?_
    _ = n - 1 := by rw [card_Ioo, tsub_zero]
    _ < n := tsub_lt_self hn.bot_lt zero_lt_one
  · rw [Finset.card_image_of_injOn, card_Iio]
    simpa using prod_primeFactors_invOn_squarefree.2.injOn.comp hf.injOn hf'
  · simp only [forall_mem_diffs, forall_image, mem_Ioo, mem_Iio]
    rintro i hi j hj
    rw [← primeFactors_div_gcd (hf' _ hi) (hf' _ hj).ne_zero,
      prod_primeFactors_of_squarefree $ hf'' _ hi _]
    exact ⟨Nat.div_pos (gcd_le_left _ (hf' _ hi).ne_zero.bot_lt) $
      Nat.gcd_pos_of_pos_left _ (hf' _ hi).ne_zero.bot_lt, Nat.div_lt_of_lt_mul $ this _ hi _ hj⟩
  · simp only [forall_mem_diffs, forall_image, mem_Ioo, mem_Iio]
    rintro a ha b hb c hc d hd
    rw [← primeFactors_div_gcd (hf' _ ha) (hf' _ hb).ne_zero, ← primeFactors_div_gcd
      (hf' _ hc) (hf' _ hd).ne_zero, prod_primeFactors_of_squarefree (hf'' _ ha _),
      prod_primeFactors_of_squarefree (hf'' _ hc _)]
    rintro h
    

Proof state:
case calc_3
n : ℕ
f : ℕ → ℕ
hf' : ∀ k < n, Squarefree (f k)
hn : n ≠ 0
hf : StrictMonoOn f (Set.Iio n)
this : ∀ i < n, ∀ j < n, f i < gcd (f i) (f j) * n
𝒜 : Finset (Finset ℕ) := image (fun n => (f n).primeFactors) (Iio n)
hf'' : ∀ i < n, ∀ (j : ℕ), Squarefree (f i / gcd (f i) (f j))
a : ℕ
ha : a < n
b : ℕ
hb : b < n
c : ℕ
hc : c < n
d : ℕ
hd : d < n
h : f a / gcd (f a) (f b) = f c / gcd (f c) (f d)
⊢ (f a / gcd (f a) (f b)).primeFactors = (f c / gcd (f c) (f d)).primeFactors

Next tactic:
rw [h]
@[simp]
theorem smul_one_eq_coe (A : Type*) [DivisionRing A] (m : ℚ) : m • (1 : A) = ↑m := by
  

Proof state:
α : Type u_1
β : Type u_2
K : Type u_3
inst✝¹ : DivisionRing K
a b : K
A : Type u_4
inst✝ : DivisionRing A
m : ℚ
⊢ m • 1 = ↑m

Next tactic:
rw [Rat.smul_def, mul_one]
lemma of_neZero_natCast (R) [AddMonoidWithOne R] {n : ℕ} [h : NeZero (n : R)] : NeZero n :=
  ⟨by 

Proof state:
R : Type u_1
inst✝ : AddMonoidWithOne R
n : ℕ
h : NeZero ↑n
⊢ n ≠ 0

Next tactic:
rintro rfl
lemma of_neZero_natCast (R) [AddMonoidWithOne R] {n : ℕ} [h : NeZero (n : R)] : NeZero n :=
  ⟨by rintro rfl; 

Proof state:
R : Type u_1
inst✝ : AddMonoidWithOne R
h : NeZero ↑0
⊢ False

Next tactic:
exact h.out Nat.cast_zero
instance [Countable ι] [∀ i, Countable (α i)] : Countable (Π₀ i, α i) := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝² : (i : ι) → Zero (α i)
inst✝¹ : Countable ι
inst✝ : ∀ (i : ι), Countable (α i)
⊢ Countable (Π₀ (i : ι), α i)

Next tactic:
classical
    let _ := Encodable.ofCountable ι
    let _ := fun i ↦ Encodable.ofCountable (α i)
    infer_instance
instance [Countable ι] [∀ i, Countable (α i)] : Countable (Π₀ i, α i) := by
  classical
    

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝² : (i : ι) → Zero (α i)
inst✝¹ : Countable ι
inst✝ : ∀ (i : ι), Countable (α i)
⊢ Countable (Π₀ (i : ι), α i)

Next tactic:
let _ := Encodable.ofCountable ι
instance [Countable ι] [∀ i, Countable (α i)] : Countable (Π₀ i, α i) := by
  classical
    let _ := Encodable.ofCountable ι
    

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝² : (i : ι) → Zero (α i)
inst✝¹ : Countable ι
inst✝ : ∀ (i : ι), Countable (α i)
x✝ : Encodable ι := Encodable.ofCountable ι
⊢ Countable (Π₀ (i : ι), α i)

Next tactic:
let _ := fun i ↦ Encodable.ofCountable (α i)
instance [Countable ι] [∀ i, Countable (α i)] : Countable (Π₀ i, α i) := by
  classical
    let _ := Encodable.ofCountable ι
    let _ := fun i ↦ Encodable.ofCountable (α i)
    

Proof state:
ι : Type u_1
α : ι → Type u_2
inst✝² : (i : ι) → Zero (α i)
inst✝¹ : Countable ι
inst✝ : ∀ (i : ι), Countable (α i)
x✝¹ : Encodable ι := Encodable.ofCountable ι
x✝ : (i : ι) → Encodable (α i) := fun i => Encodable.ofCountable (α i)
⊢ Countable (Π₀ (i : ι), α i)

Next tactic:
infer_instance
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
⊢ IsClosed ↑U

Next tactic:
apply isOpen_compl_iff.1
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
⊢ IsOpen (↑U)ᶜ

Next tactic:
refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · 

Proof state:
case refine'_1
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
⊢ (fun y => y * x⁻¹) ⁻¹' ↑U ⊆ (↑U)ᶜ

Next tactic:
refine' fun u hux hu => hx _
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · refine' fun u hux hu => hx _
    

Proof state:
case refine'_1
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
u : G
hux : u ∈ (fun y => y * x⁻¹) ⁻¹' ↑U
hu : u ∈ ↑U
⊢ x ∈ ↑U

Next tactic:
simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · refine' fun u hux hu => hx _
    simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢
    

Proof state:
case refine'_1
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
u : G
hux : u * x⁻¹ ∈ U
hu : u ∈ U
⊢ x ∈ U

Next tactic:
convert U.mul_mem (U.inv_mem hux) hu
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · refine' fun u hux hu => hx _
    simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢
    convert U.mul_mem (U.inv_mem hux) hu
    

Proof state:
case a
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
u : G
hux : u * x⁻¹ ∈ U
hu : u ∈ U
⊢ x ∈ U ↔ (u * x⁻¹)⁻¹ * u ∈ ↑U

Next tactic:
simp
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · refine' fun u hux hu => hx _
    simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢
    convert U.mul_mem (U.inv_mem hux) hu
    simp
  · 

Proof state:
case refine'_2
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
⊢ IsOpen ((fun y => y * x⁻¹) ⁻¹' ↑U)

Next tactic:
exact U.isOpen.preimage (continuous_mul_right _)
@[to_additive]
theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by
  apply isOpen_compl_iff.1
  refine' isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, _, _, _⟩
  · refine' fun u hux hu => hx _
    simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢
    convert U.mul_mem (U.inv_mem hux) hu
    simp
  · exact U.isOpen.preimage (continuous_mul_right _)
  · 

Proof state:
case refine'_3
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
U✝ V : OpenSubgroup G
g : G
inst✝ : ContinuousMul G
U : OpenSubgroup G
x : G
hx : x ∈ (↑U)ᶜ
⊢ x ∈ (fun y => y * x⁻¹) ⁻¹' ↑U

Next tactic:
simp [one_mem]
@[to_additive]
theorem isOpen_of_mem_nhds {g : G} (hg : (H : Set G) ∈ 𝓝 g) : IsOpen (H : Set G) := by
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
inst✝ : ContinuousMul G
H : Subgroup G
g : G
hg : ↑H ∈ 𝓝 g
⊢ IsOpen ↑H

Next tactic:
refine' isOpen_iff_mem_nhds.2 fun x hx => _
@[to_additive]
theorem isOpen_of_mem_nhds {g : G} (hg : (H : Set G) ∈ 𝓝 g) : IsOpen (H : Set G) := by
  refine' isOpen_iff_mem_nhds.2 fun x hx => _
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
inst✝ : ContinuousMul G
H : Subgroup G
g : G
hg : ↑H ∈ 𝓝 g
x : G
hx : x ∈ ↑H
⊢ ↑H ∈ 𝓝 x

Next tactic:
have hg' : g ∈ H := SetLike.mem_coe.1 (mem_of_mem_nhds hg)
@[to_additive]
theorem isOpen_of_mem_nhds {g : G} (hg : (H : Set G) ∈ 𝓝 g) : IsOpen (H : Set G) := by
  refine' isOpen_iff_mem_nhds.2 fun x hx => _
  have hg' : g ∈ H := SetLike.mem_coe.1 (mem_of_mem_nhds hg)
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
inst✝ : ContinuousMul G
H : Subgroup G
g : G
hg : ↑H ∈ 𝓝 g
x : G
hx : x ∈ ↑H
hg' : g ∈ H
⊢ ↑H ∈ 𝓝 x

Next tactic:
have : Filter.Tendsto (fun y => y * (x⁻¹ * g)) (𝓝 x) (𝓝 g) :=
    (continuous_id.mul continuous_const).tendsto' _ _ (mul_inv_cancel_left _ _)
@[to_additive]
theorem isOpen_of_mem_nhds {g : G} (hg : (H : Set G) ∈ 𝓝 g) : IsOpen (H : Set G) := by
  refine' isOpen_iff_mem_nhds.2 fun x hx => _
  have hg' : g ∈ H := SetLike.mem_coe.1 (mem_of_mem_nhds hg)
  have : Filter.Tendsto (fun y => y * (x⁻¹ * g)) (𝓝 x) (𝓝 g) :=
    (continuous_id.mul continuous_const).tendsto' _ _ (mul_inv_cancel_left _ _)
  

Proof state:
G : Type u_1
inst✝² : Group G
inst✝¹ : TopologicalSpace G
inst✝ : ContinuousMul G
H : Subgroup G
g : G
hg : ↑H ∈ 𝓝 g
x : G
hx : x ∈ ↑H
hg' : g ∈ H
this : Filter.Tendsto (fun y => y * (x⁻¹ * g)) (𝓝 x) (𝓝 g)
⊢ ↑H ∈ 𝓝 x

Next tactic:
simpa only [SetLike.mem_coe, Filter.mem_map',
    H.mul_mem_cancel_right (H.mul_mem (H.inv_mem hx) hg')] using this hg
/-- `Cone.toStructuredArrow` can be expressed in terms of `Functor.toStructuredArrow`. -/
def Cone.toStructuredArrowIsoToStructuredArrow {F : J ⥤ C} (c : Cone F) :
    c.toStructuredArrow ≅ (𝟭 J).toStructuredArrow c.pt F c.π.app (by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cone F
⊢ ∀ {Y Z : J} (g : Y ⟶ Z), c.π.app Y ≫ F.map ((𝟭 J).map g) = c.π.app Z

Next tactic:
simp
/-- `Functor.toStructuredArrow` can be expressed in terms of `Cone.toStructuredArrow`. -/
def _root_.CategoryTheory.Functor.toStructuredArrowIsoToStructuredArrow (G : J ⥤ K) (X : C)
    (F : K ⥤ C) (f : (Y : J) → X ⟶ F.obj (G.obj Y))
    (h : ∀ {Y Z : J} (g : Y ⟶ Z), f Y ≫ F.map (G.map g) = f Z) :
    G.toStructuredArrow X F f h ≅
      (Cone.mk X ⟨f, by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
G : J ⥤ K
X : C
F : K ⥤ C
f : (Y : J) → X ⟶ F.obj (G.obj Y)
h : ∀ {Y Z : J} (g : Y ⟶ Z), f Y ≫ F.map (G.map g) = f Z
⊢ ∀ ⦃X_1 Y : J⦄ (f_1 : X_1 ⟶ Y), ((const J).obj X).map f_1 ≫ f Y = f X_1 ≫ (G ⋙ F).map f_1

Next tactic:
simp [h]
/-- Construct a cone on `F` from an object of the category `(Δ ↓ F)`. This is part of an
    equivalence, see `Cone.equivCostructuredArrow`. -/
@[simps]
def Cone.fromCostructuredArrow (F : J ⥤ C) : CostructuredArrow (const J) F ⥤ Cone F
    where
  obj c := ⟨c.left, c.hom⟩
  map f :=
    { hom := f.left
      w := fun j => by
        

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : CostructuredArrow (const J) F
f : X✝ ⟶ Y✝
j : J
⊢ f.left ≫ ((fun c => { pt := c.left, π := c.hom }) Y✝).π.app j = ((fun c => { pt := c.left, π := c.hom }) X✝).π.app j

Next tactic:
convert congr_fun (congr_arg NatTrans.app f.w) j
/-- Construct a cone on `F` from an object of the category `(Δ ↓ F)`. This is part of an
    equivalence, see `Cone.equivCostructuredArrow`. -/
@[simps]
def Cone.fromCostructuredArrow (F : J ⥤ C) : CostructuredArrow (const J) F ⥤ Cone F
    where
  obj c := ⟨c.left, c.hom⟩
  map f :=
    { hom := f.left
      w := fun j => by
        convert congr_fun (congr_arg NatTrans.app f.w) j
        

Proof state:
case h.e'_3.h.h.e'_7.h
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : CostructuredArrow (const J) F
f : X✝ ⟶ Y✝
j : J
e_1✝ :
  (((fun c => { pt := c.left, π := c.hom }) X✝).pt ⟶ F.obj j) =
    (((const J).obj X✝.left).obj j ⟶ ((fromPUnit F).obj Y✝.right).obj j)
e_6✝ : F = (fromPUnit F).obj Y✝.right
⊢ ((fun c => { pt := c.left, π := c.hom }) X✝).π = X✝.hom ≫ (fromPUnit F).map f.right

Next tactic:
dsimp
/-- Construct a cone on `F` from an object of the category `(Δ ↓ F)`. This is part of an
    equivalence, see `Cone.equivCostructuredArrow`. -/
@[simps]
def Cone.fromCostructuredArrow (F : J ⥤ C) : CostructuredArrow (const J) F ⥤ Cone F
    where
  obj c := ⟨c.left, c.hom⟩
  map f :=
    { hom := f.left
      w := fun j => by
        convert congr_fun (congr_arg NatTrans.app f.w) j
        dsimp
        

Proof state:
case h.e'_3.h.h.e'_7.h
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : CostructuredArrow (const J) F
f : X✝ ⟶ Y✝
j : J
e_1✝ :
  (((fun c => { pt := c.left, π := c.hom }) X✝).pt ⟶ F.obj j) =
    (((const J).obj X✝.left).obj j ⟶ ((fromPUnit F).obj Y✝.right).obj j)
e_6✝ : F = (fromPUnit F).obj Y✝.right
⊢ X✝.hom = X✝.hom ≫ 𝟙 F

Next tactic:
simp
/-- A cone is a limit cone iff it is terminal. -/
def Cone.isLimitEquivIsTerminal {F : J ⥤ C} (c : Cone F) : IsLimit c ≃ IsTerminal c :=
  IsLimit.isoUniqueConeMorphism.toEquiv.trans
    { toFun := fun h => IsTerminal.ofUnique _
      invFun := fun h s => ⟨⟨IsTerminal.from h s⟩, fun a => IsTerminal.hom_ext h a _⟩
      left_inv := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cone F
⊢ Function.LeftInverse
    (fun h s => { toInhabited := { default := IsTerminal.from h s }, uniq := (_ : ∀ (a : s ⟶ c), a = default) })
    fun h => IsTerminal.ofUnique c

Next tactic:
aesop_cat
/-- A cone is a limit cone iff it is terminal. -/
def Cone.isLimitEquivIsTerminal {F : J ⥤ C} (c : Cone F) : IsLimit c ≃ IsTerminal c :=
  IsLimit.isoUniqueConeMorphism.toEquiv.trans
    { toFun := fun h => IsTerminal.ofUnique _
      invFun := fun h s => ⟨⟨IsTerminal.from h s⟩, fun a => IsTerminal.hom_ext h a _⟩
      left_inv := by aesop_cat
      right_inv := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cone F
⊢ Function.RightInverse
    (fun h s => { toInhabited := { default := IsTerminal.from h s }, uniq := (_ : ∀ (a : s ⟶ c), a = default) })
    fun h => IsTerminal.ofUnique c

Next tactic:
aesop_cat
/-- `Cocone.toCostructuredArrow` can be expressed in terms of `Functor.toCostructuredArrow`. -/
def Cocone.toCostructuredArrowIsoToCostructuredArrow {F : J ⥤ C} (c : Cocone F) :
    c.toCostructuredArrow ≅ (𝟭 J).toCostructuredArrow F c.pt c.ι.app (by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cocone F
⊢ ∀ {Y Z : J} (g : Y ⟶ Z), F.map ((𝟭 J).map g) ≫ c.ι.app Z = c.ι.app Y

Next tactic:
simp
/-- `Functor.toCostructuredArrow` can be expressed in terms of `Cocone.toCostructuredArrow`. -/
def _root_.CategoryTheory.Functor.toCostructuredArrowIsoToCostructuredArrow (G : J ⥤ K)
    (F : K ⥤ C) (X : C) (f : (Y : J) → F.obj (G.obj Y) ⟶ X)
    (h : ∀ {Y Z : J} (g : Y ⟶ Z), F.map (G.map g) ≫ f Z = f Y) :
    G.toCostructuredArrow F X f h ≅
      (Cocone.mk X ⟨f, by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
G : J ⥤ K
F : K ⥤ C
X : C
f : (Y : J) → F.obj (G.obj Y) ⟶ X
h : ∀ {Y Z : J} (g : Y ⟶ Z), F.map (G.map g) ≫ f Z = f Y
⊢ ∀ ⦃X_1 Y : J⦄ (f_1 : X_1 ⟶ Y), (G ⋙ F).map f_1 ≫ f Y = f X_1 ≫ ((const J).obj X).map f_1

Next tactic:
simp [h]
/-- Construct a cocone on `F` from an object of the category `(F ↓ Δ)`. This is part of an
    equivalence, see `Cocone.equivStructuredArrow`. -/
@[simps]
def Cocone.fromStructuredArrow (F : J ⥤ C) : StructuredArrow F (const J) ⥤ Cocone F
    where
  obj c := ⟨c.right, c.hom⟩
  map f :=
    { hom := f.right
      w := fun j => by
        

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : StructuredArrow F (const J)
f : X✝ ⟶ Y✝
j : J
⊢ ((fun c => { pt := c.right, ι := c.hom }) X✝).ι.app j ≫ f.right =
    ((fun c => { pt := c.right, ι := c.hom }) Y✝).ι.app j

Next tactic:
convert (congr_fun (congr_arg NatTrans.app f.w) j).symm
/-- Construct a cocone on `F` from an object of the category `(F ↓ Δ)`. This is part of an
    equivalence, see `Cocone.equivStructuredArrow`. -/
@[simps]
def Cocone.fromStructuredArrow (F : J ⥤ C) : StructuredArrow F (const J) ⥤ Cocone F
    where
  obj c := ⟨c.right, c.hom⟩
  map f :=
    { hom := f.right
      w := fun j => by
        convert (congr_fun (congr_arg NatTrans.app f.w) j).symm
        

Proof state:
case h.e'_3.h.h.e'_7.h
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : StructuredArrow F (const J)
f : X✝ ⟶ Y✝
j : J
e_1✝ :
  (F.obj j ⟶ ((fun c => { pt := c.right, ι := c.hom }) Y✝).pt) =
    (((fromPUnit F).obj X✝.left).obj j ⟶ ((const J).obj Y✝.right).obj j)
e_5✝ : F = (fromPUnit F).obj X✝.left
⊢ ((fun c => { pt := c.right, ι := c.hom }) Y✝).ι = (fromPUnit F).map f.left ≫ Y✝.hom

Next tactic:
dsimp
/-- Construct a cocone on `F` from an object of the category `(F ↓ Δ)`. This is part of an
    equivalence, see `Cocone.equivStructuredArrow`. -/
@[simps]
def Cocone.fromStructuredArrow (F : J ⥤ C) : StructuredArrow F (const J) ⥤ Cocone F
    where
  obj c := ⟨c.right, c.hom⟩
  map f :=
    { hom := f.right
      w := fun j => by
        convert (congr_fun (congr_arg NatTrans.app f.w) j).symm
        dsimp
        

Proof state:
case h.e'_3.h.h.e'_7.h
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
X✝ Y✝ : StructuredArrow F (const J)
f : X✝ ⟶ Y✝
j : J
e_1✝ :
  (F.obj j ⟶ ((fun c => { pt := c.right, ι := c.hom }) Y✝).pt) =
    (((fromPUnit F).obj X✝.left).obj j ⟶ ((const J).obj Y✝.right).obj j)
e_5✝ : F = (fromPUnit F).obj X✝.left
⊢ Y✝.hom = 𝟙 F ≫ Y✝.hom

Next tactic:
simp
/-- A cocone is a colimit cocone iff it is initial. -/
def Cocone.isColimitEquivIsInitial {F : J ⥤ C} (c : Cocone F) : IsColimit c ≃ IsInitial c :=
  IsColimit.isoUniqueCoconeMorphism.toEquiv.trans
    { toFun := fun h => IsInitial.ofUnique _
      invFun := fun h s => ⟨⟨IsInitial.to h s⟩, fun a => IsInitial.hom_ext h a _⟩
      left_inv := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cocone F
⊢ Function.LeftInverse
    (fun h s => { toInhabited := { default := IsInitial.to h s }, uniq := (_ : ∀ (a : c ⟶ s), a = default) }) fun h =>
    IsInitial.ofUnique c

Next tactic:
aesop_cat
/-- A cocone is a colimit cocone iff it is initial. -/
def Cocone.isColimitEquivIsInitial {F : J ⥤ C} (c : Cocone F) : IsColimit c ≃ IsInitial c :=
  IsColimit.isoUniqueCoconeMorphism.toEquiv.trans
    { toFun := fun h => IsInitial.ofUnique _
      invFun := fun h s => ⟨⟨IsInitial.to h s⟩, fun a => IsInitial.hom_ext h a _⟩
      left_inv := by aesop_cat
      right_inv := by 

Proof state:
J : Type u₁
inst✝³ : Category.{v₁, u₁} J
K : Type u₂
inst✝² : Category.{v₂, u₂} K
C : Type u₃
inst✝¹ : Category.{v₃, u₃} C
D : Type u₄
inst✝ : Category.{v₄, u₄} D
F : J ⥤ C
c : Cocone F
⊢ Function.RightInverse
    (fun h s => { toInhabited := { default := IsInitial.to h s }, uniq := (_ : ∀ (a : c ⟶ s), a = default) }) fun h =>
    IsInitial.ofUnique c

Next tactic:
aesop_cat
@[simp]
theorem cardinal_mk_eq_max {R : Type u} [Semiring R] [Nontrivial R] : #(R[X]) = max #R ℵ₀ :=
  (toFinsuppIso R).toEquiv.cardinal_eq.trans <| by
    

Proof state:
R : Type u
inst✝¹ : Semiring R
inst✝ : Nontrivial R
⊢ #(AddMonoidAlgebra R ℕ) = max #R ℵ₀

Next tactic:
rw [AddMonoidAlgebra, mk_finsupp_lift_of_infinite, lift_uzero, max_comm]
@[simp]
theorem cardinal_mk_eq_max {R : Type u} [Semiring R] [Nontrivial R] : #(R[X]) = max #R ℵ₀ :=
  (toFinsuppIso R).toEquiv.cardinal_eq.trans <| by
    rw [AddMonoidAlgebra, mk_finsupp_lift_of_infinite, lift_uzero, max_comm]
    

Proof state:
R : Type u
inst✝¹ : Semiring R
inst✝ : Nontrivial R
⊢ max (#R) (lift.{u, 0} #ℕ) = max #R ℵ₀

Next tactic:
rfl
theorem cardinal_mk_le_max {R : Type u} [Semiring R] : #(R[X]) ≤ max #R ℵ₀ := by
  

Proof state:
R : Type u
inst✝ : Semiring R
⊢ #R[X] ≤ max #R ℵ₀

Next tactic:
cases subsingleton_or_nontrivial R
theorem cardinal_mk_le_max {R : Type u} [Semiring R] : #(R[X]) ≤ max #R ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · 

Proof state:
case inl
R : Type u
inst✝ : Semiring R
h✝ : Subsingleton R
⊢ #R[X] ≤ max #R ℵ₀

Next tactic:
exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
theorem cardinal_mk_le_max {R : Type u} [Semiring R] : #(R[X]) ≤ max #R ℵ₀ := by
  cases subsingleton_or_nontrivial R
  · exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0)
  · 

Proof state:
case inr
R : Type u
inst✝ : Semiring R
h✝ : Nontrivial R
⊢ #R[X] ≤ max #R ℵ₀

Next tactic:
exact cardinal_mk_eq_max.le
/-- Under some conditions on the `MorphismProperty`, functors satisfying the strict
universal property of the localization are stable under composition -/
def StrictUniversalPropertyFixedTarget.comp
    (h₁ : StrictUniversalPropertyFixedTarget L₁ W₁ E)
    (h₂ : StrictUniversalPropertyFixedTarget L₂ W₂ E)
    (W₃ : MorphismProperty C₁) (hW₃ : W₃.IsInvertedBy (L₁ ⋙ L₂))
    (hW₁₃ : W₁ ⊆ W₃) (hW₂₃ : W₂ ⊆ W₃.map L₁) :
    StrictUniversalPropertyFixedTarget (L₁ ⋙ L₂) W₃ E where
  inverts := hW₃
  lift F hF := h₂.lift (h₁.lift F (MorphismProperty.IsInvertedBy.of_subset _ _  F hF hW₁₃)) (by
    

Proof state:
C₁ : Type u₁
C₂ : Type u₂
C₃ : Type u₃
E : Type u₄
inst✝³ : Category.{v₁, u₁} C₁
inst✝² : Category.{v₂, u₂} C₂
inst✝¹ : Category.{v₃, u₃} C₃
inst✝ : Category.{v₄, u₄} E
L₁ : C₁ ⥤ C₂
L₂ : C₂ ⥤ C₃
W₁ : MorphismProperty C₁
W₂ : MorphismProperty C₂
h₁ : StrictUniversalPropertyFixedTarget L₁ W₁ E
h₂ : StrictUniversalPropertyFixedTarget L₂ W₂ E
W₃ : MorphismProperty C₁
hW₃ : MorphismProperty.IsInvertedBy W₃ (L₁ ⋙ L₂)
hW₁₃ : W₁ ⊆ W₃
hW₂₃ : W₂ ⊆ MorphismProperty.map W₃ L₁
F : C₁ ⥤ E
hF : MorphismProperty.IsInvertedBy W₃ F
⊢ MorphismProperty.IsInvertedBy W₂ (lift h₁ F (_ : MorphismProperty.IsInvertedBy W₁ F))

Next tactic:
refine' MorphismProperty.IsInvertedBy.of_subset _ _ _ _ hW₂₃