l3lab/ntp-mathlib huggingface dataset:
/-- Torsion submonoids are torsion. -/
@[to_additive "Additive torsion submonoids are additively torsion."]
theorem torsion.isTorsion : IsTorsion <| torsion G := fun ⟨x, n, npos, hn⟩ =>
  ⟨n, npos,
    Subtype.ext <| by
      dsimp
      rw [mul_left_iterate]
      change _ * 1 = 1
      

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
x✝ : ↥(torsion G)
x : G
n : ℕ
npos : n > 0
hn : Function.IsPeriodicPt (fun x_1 => x * x_1) n 1
⊢ ↑({ val := x, property := (_ : ∃ n > 0, Function.IsPeriodicPt (fun x_1 => x * x_1) n 1) } ^ n) * 1 = 1

Next tactic:
rw [_root_.mul_one, SubmonoidClass.coe_pow, Subtype.coe_mk,
        (isPeriodicPt_mul_iff_pow_eq_one _).mp hn]
/-- The `p`-primary component is the submonoid of elements with order prime-power of `p`. -/
@[to_additive (attr := simps)
      "The `p`-primary component is the submonoid of elements with additive
      order prime-power of `p`."]
def primaryComponent : Submonoid G where
  carrier := { g | ∃ n : ℕ, orderOf g = p ^ n }
  one_mem' := ⟨0, by rw [pow_zero, orderOf_one]⟩
  mul_mem' hg₁ hg₂ :=
    exists_orderOf_eq_prime_pow_iff.mpr <| by
      

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
a✝ b✝ : G
hg₁ : a✝ ∈ {g | ∃ n, orderOf g = p ^ n}
hg₂ : b✝ ∈ {g | ∃ n, orderOf g = p ^ n}
⊢ ∃ m, (a✝ * b✝) ^ p ^ m = 1

Next tactic:
obtain ⟨m, hm⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₁
/-- The `p`-primary component is the submonoid of elements with order prime-power of `p`. -/
@[to_additive (attr := simps)
      "The `p`-primary component is the submonoid of elements with additive
      order prime-power of `p`."]
def primaryComponent : Submonoid G where
  carrier := { g | ∃ n : ℕ, orderOf g = p ^ n }
  one_mem' := ⟨0, by rw [pow_zero, orderOf_one]⟩
  mul_mem' hg₁ hg₂ :=
    exists_orderOf_eq_prime_pow_iff.mpr <| by
      obtain ⟨m, hm⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₁
      

Proof state:
case intro
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
a✝ b✝ : G
hg₁ : a✝ ∈ {g | ∃ n, orderOf g = p ^ n}
hg₂ : b✝ ∈ {g | ∃ n, orderOf g = p ^ n}
m : ℕ
hm : a✝ ^ p ^ m = 1
⊢ ∃ m, (a✝ * b✝) ^ p ^ m = 1

Next tactic:
obtain ⟨n, hn⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₂
/-- The `p`-primary component is the submonoid of elements with order prime-power of `p`. -/
@[to_additive (attr := simps)
      "The `p`-primary component is the submonoid of elements with additive
      order prime-power of `p`."]
def primaryComponent : Submonoid G where
  carrier := { g | ∃ n : ℕ, orderOf g = p ^ n }
  one_mem' := ⟨0, by rw [pow_zero, orderOf_one]⟩
  mul_mem' hg₁ hg₂ :=
    exists_orderOf_eq_prime_pow_iff.mpr <| by
      obtain ⟨m, hm⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₁
      obtain ⟨n, hn⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₂
      

Proof state:
case intro.intro
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
a✝ b✝ : G
hg₁ : a✝ ∈ {g | ∃ n, orderOf g = p ^ n}
hg₂ : b✝ ∈ {g | ∃ n, orderOf g = p ^ n}
m : ℕ
hm : a✝ ^ p ^ m = 1
n : ℕ
hn : b✝ ^ p ^ n = 1
⊢ ∃ m, (a✝ * b✝) ^ p ^ m = 1

Next tactic:
exact
        ⟨m + n, by
          rw [mul_pow, pow_add, pow_mul, hm, one_pow, Monoid.one_mul, mul_comm, pow_mul, hn,
            one_pow]⟩
/-- The `p`-primary component is the submonoid of elements with order prime-power of `p`. -/
@[to_additive (attr := simps)
      "The `p`-primary component is the submonoid of elements with additive
      order prime-power of `p`."]
def primaryComponent : Submonoid G where
  carrier := { g | ∃ n : ℕ, orderOf g = p ^ n }
  one_mem' := ⟨0, by rw [pow_zero, orderOf_one]⟩
  mul_mem' hg₁ hg₂ :=
    exists_orderOf_eq_prime_pow_iff.mpr <| by
      obtain ⟨m, hm⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₁
      obtain ⟨n, hn⟩ := exists_orderOf_eq_prime_pow_iff.mp hg₂
      exact
        ⟨m + n, by
          

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
a✝ b✝ : G
hg₁ : a✝ ∈ {g | ∃ n, orderOf g = p ^ n}
hg₂ : b✝ ∈ {g | ∃ n, orderOf g = p ^ n}
m : ℕ
hm : a✝ ^ p ^ m = 1
n : ℕ
hn : b✝ ^ p ^ n = 1
⊢ (a✝ * b✝) ^ p ^ (m + n) = 1

Next tactic:
rw [mul_pow, pow_add, pow_mul, hm, one_pow, Monoid.one_mul, mul_comm, pow_mul, hn,
            one_pow]
/-- The `p`-primary component is the submonoid of elements with order prime-power of `p`. -/
@[to_additive (attr := simps)
      "The `p`-primary component is the submonoid of elements with additive
      order prime-power of `p`."]
def primaryComponent : Submonoid G where
  carrier := { g | ∃ n : ℕ, orderOf g = p ^ n }
  one_mem' := ⟨0, by 

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
⊢ orderOf 1 = p ^ 0

Next tactic:
rw [pow_zero, orderOf_one]
/-- Elements of the `p`-primary component have order `p^n` for some `n`. -/
@[to_additive primaryComponent.exists_orderOf_eq_prime_nsmul
  "Elements of the `p`-primary component have additive order `p^n` for some `n`"]
theorem primaryComponent.exists_orderOf_eq_prime_pow (g : CommMonoid.primaryComponent G p) :
    ∃ n : ℕ, orderOf g = p ^ n := by 

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
g : ↥(primaryComponent G p)
⊢ ∃ n, orderOf g = p ^ n

Next tactic:
simpa [primaryComponent] using g.property
/-- The `p`- and `q`-primary components are disjoint for `p ≠ q`. -/
@[to_additive "The `p`- and `q`-primary components are disjoint for `p ≠ q`."]
theorem primaryComponent.disjoint {p' : ℕ} [hp' : Fact p'.Prime] (hne : p ≠ p') :
    Disjoint (CommMonoid.primaryComponent G p) (CommMonoid.primaryComponent G p') :=
  Submonoid.disjoint_def.mpr <| by
    

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
p' : ℕ
hp' : Fact (Nat.Prime p')
hne : p ≠ p'
⊢ ∀ {x : G}, x ∈ primaryComponent G p → x ∈ primaryComponent G p' → x = 1

Next tactic:
rintro g ⟨_ | n, hn⟩ ⟨n', hn'⟩
/-- The `p`- and `q`-primary components are disjoint for `p ≠ q`. -/
@[to_additive "The `p`- and `q`-primary components are disjoint for `p ≠ q`."]
theorem primaryComponent.disjoint {p' : ℕ} [hp' : Fact p'.Prime] (hne : p ≠ p') :
    Disjoint (CommMonoid.primaryComponent G p) (CommMonoid.primaryComponent G p') :=
  Submonoid.disjoint_def.mpr <| by
    rintro g ⟨_ | n, hn⟩ ⟨n', hn'⟩
    · 

Proof state:
case intro.zero.intro
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
p' : ℕ
hp' : Fact (Nat.Prime p')
hne : p ≠ p'
g : G
hn : orderOf g = p ^ Nat.zero
n' : ℕ
hn' : orderOf g = p' ^ n'
⊢ g = 1

Next tactic:
rwa [pow_zero, orderOf_eq_one_iff] at hn
/-- The `p`- and `q`-primary components are disjoint for `p ≠ q`. -/
@[to_additive "The `p`- and `q`-primary components are disjoint for `p ≠ q`."]
theorem primaryComponent.disjoint {p' : ℕ} [hp' : Fact p'.Prime] (hne : p ≠ p') :
    Disjoint (CommMonoid.primaryComponent G p) (CommMonoid.primaryComponent G p') :=
  Submonoid.disjoint_def.mpr <| by
    rintro g ⟨_ | n, hn⟩ ⟨n', hn'⟩
    · rwa [pow_zero, orderOf_eq_one_iff] at hn
    · 

Proof state:
case intro.succ.intro
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
p : ℕ
hp : Fact (Nat.Prime p)
p' : ℕ
hp' : Fact (Nat.Prime p')
hne : p ≠ p'
g : G
n : ℕ
hn : orderOf g = p ^ Nat.succ n
n' : ℕ
hn' : orderOf g = p' ^ n'
⊢ g = 1

Next tactic:
exact
        absurd (eq_of_prime_pow_eq hp.out.prime hp'.out.prime n.succ_pos (hn.symm.trans hn')) hne
/-- The torsion submonoid of a torsion monoid is `⊤`. -/
@[to_additive (attr := simp) "The additive torsion submonoid of an additive torsion monoid is `⊤`."]
theorem torsion_eq_top (tG : IsTorsion G) : torsion G = ⊤ := by 

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
tG : IsTorsion G
⊢ torsion G = ⊤

Next tactic:
ext
/-- The torsion submonoid of a torsion monoid is `⊤`. -/
@[to_additive (attr := simp) "The additive torsion submonoid of an additive torsion monoid is `⊤`."]
theorem torsion_eq_top (tG : IsTorsion G) : torsion G = ⊤ := by ext; 

Proof state:
case h
G : Type u_1
H : Type u_2
inst✝ : CommMonoid G
tG : IsTorsion G
x✝ : G
⊢ x✝ ∈ torsion G ↔ x✝ ∈ ⊤

Next tactic:
tauto
/-- A nontrivial monoid is not torsion-free if any nontrivial element has finite order. -/
@[to_additive (attr := simp) "An additive monoid is not torsion free if any
  nontrivial element has finite order."]
theorem not_isTorsionFree_iff : ¬IsTorsionFree G ↔ ∃ g : G, g ≠ 1 ∧ IsOfFinOrder g := by
  

Proof state:
G : Type u_1
H : Type u_2
inst✝ : Monoid G
⊢ ¬IsTorsionFree G ↔ ∃ g, g ≠ 1 ∧ IsOfFinOrder g

Next tactic:
simp_rw [IsTorsionFree, Ne.def, not_forall, Classical.not_not, exists_prop]
/-- A nontrivial torsion group is not torsion-free. -/
@[to_additive AddMonoid.IsTorsion.not_torsion_free
      "A nontrivial additive torsion group is not torsion-free."]
theorem IsTorsion.not_torsion_free [hN : Nontrivial G] : IsTorsion G → ¬IsTorsionFree G := fun tG =>
  not_isTorsionFree_iff.mpr <| by
    

Proof state:
G : Type u_1
H : Type u_2
inst✝ : Group G
hN : Nontrivial G
tG : IsTorsion G
⊢ ∃ g, g ≠ 1 ∧ IsOfFinOrder g

Next tactic:
obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN
/-- A nontrivial torsion group is not torsion-free. -/
@[to_additive AddMonoid.IsTorsion.not_torsion_free
      "A nontrivial additive torsion group is not torsion-free."]
theorem IsTorsion.not_torsion_free [hN : Nontrivial G] : IsTorsion G → ¬IsTorsionFree G := fun tG =>
  not_isTorsionFree_iff.mpr <| by
    obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN
    

Proof state:
case intro
G : Type u_1
H : Type u_2
inst✝ : Group G
hN : Nontrivial G
tG : IsTorsion G
x : G
hx : x ≠ 1
⊢ ∃ g, g ≠ 1 ∧ IsOfFinOrder g

Next tactic:
exact ⟨x, hx, tG x⟩
/-- A nontrivial torsion-free group is not torsion. -/
@[to_additive AddMonoid.IsTorsionFree.not_torsion
      "A nontrivial torsion-free additive group is not torsion."]
theorem IsTorsionFree.not_torsion [hN : Nontrivial G] : IsTorsionFree G → ¬IsTorsion G := fun tfG =>
  (not_isTorsion_iff _).mpr <| by
    

Proof state:
G : Type u_1
H : Type u_2
inst✝ : Group G
hN : Nontrivial G
tfG : IsTorsionFree G
⊢ ∃ g, ¬IsOfFinOrder g

Next tactic:
obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN
/-- A nontrivial torsion-free group is not torsion. -/
@[to_additive AddMonoid.IsTorsionFree.not_torsion
      "A nontrivial torsion-free additive group is not torsion."]
theorem IsTorsionFree.not_torsion [hN : Nontrivial G] : IsTorsionFree G → ¬IsTorsion G := fun tfG =>
  (not_isTorsion_iff _).mpr <| by
    obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN
    

Proof state:
case intro
G : Type u_1
H : Type u_2
inst✝ : Group G
hN : Nontrivial G
tfG : IsTorsionFree G
x : G
hx : x ≠ 1
⊢ ∃ g, ¬IsOfFinOrder g

Next tactic:
exact ⟨x, (tfG x) hx⟩
/-- Subgroups of torsion-free groups are torsion-free. -/
@[to_additive "Subgroups of additive torsion-free groups are additively torsion-free."]
theorem IsTorsionFree.subgroup (tG : IsTorsionFree G) (H : Subgroup G) : IsTorsionFree H :=
  fun h hne ↦ Submonoid.isOfFinOrder_coe.not.1 <| tG h <| by 

Proof state:
G : Type u_1
H✝ : Type u_2
inst✝ : Group G
tG : IsTorsionFree G
H : Subgroup G
h : ↥H
hne : h ≠ 1
⊢ ↑h ≠ 1

Next tactic:
norm_cast
/-- Quotienting a group by its torsion subgroup yields a torsion free group. -/
@[to_additive AddIsTorsionFree.quotient_torsion
      "Quotienting a group by its additive torsion subgroup yields an additive torsion free group."]
theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun g hne hfin =>
  hne <| by
    

Proof state:
G : Type u_1
H : Type u_2
inst✝ : CommGroup G
g : G ⧸ torsion G
hne : g ≠ 1
hfin : IsOfFinOrder g
⊢ g = 1

Next tactic:
induction' g using QuotientGroup.induction_on' with g
/-- Quotienting a group by its torsion subgroup yields a torsion free group. -/
@[to_additive AddIsTorsionFree.quotient_torsion
      "Quotienting a group by its additive torsion subgroup yields an additive torsion free group."]
theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun g hne hfin =>
  hne <| by
    induction' g using QuotientGroup.induction_on' with g
    

Proof state:
case H
G : Type u_1
H : Type u_2
inst✝ : CommGroup G
g : G
hne : ↑g ≠ 1
hfin : IsOfFinOrder ↑g
⊢ ↑g = 1

Next tactic:
obtain ⟨m, mpos, hm⟩ := hfin.exists_pow_eq_one
/-- Quotienting a group by its torsion subgroup yields a torsion free group. -/
@[to_additive AddIsTorsionFree.quotient_torsion
      "Quotienting a group by its additive torsion subgroup yields an additive torsion free group."]
theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun g hne hfin =>
  hne <| by
    induction' g using QuotientGroup.induction_on' with g
    obtain ⟨m, mpos, hm⟩ := hfin.exists_pow_eq_one
    

Proof state:
case H.intro.intro
G : Type u_1
H : Type u_2
inst✝ : CommGroup G
g : G
hne : ↑g ≠ 1
hfin : IsOfFinOrder ↑g
m : ℕ
mpos : 0 < m
hm : ↑g ^ m = 1
⊢ ↑g = 1

Next tactic:
obtain ⟨n, npos, hn⟩ := ((QuotientGroup.eq_one_iff _).mp hm).exists_pow_eq_one
/-- Quotienting a group by its torsion subgroup yields a torsion free group. -/
@[to_additive AddIsTorsionFree.quotient_torsion
      "Quotienting a group by its additive torsion subgroup yields an additive torsion free group."]
theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun g hne hfin =>
  hne <| by
    induction' g using QuotientGroup.induction_on' with g
    obtain ⟨m, mpos, hm⟩ := hfin.exists_pow_eq_one
    obtain ⟨n, npos, hn⟩ := ((QuotientGroup.eq_one_iff _).mp hm).exists_pow_eq_one
    

Proof state:
case H.intro.intro.intro.intro
G : Type u_1
H : Type u_2
inst✝ : CommGroup G
g : G
hne : ↑g ≠ 1
hfin : IsOfFinOrder ↑g
m : ℕ
mpos : 0 < m
hm : ↑g ^ m = 1
n : ℕ
npos : 0 < n
hn : (fun x => x ^ m) g ^ n = 1
⊢ ↑g = 1

Next tactic:
exact
      (QuotientGroup.eq_one_iff g).mpr
        (isOfFinOrder_iff_pow_eq_one.mpr ⟨m * n, mul_pos mpos npos, (pow_mul g m n).symm ▸ hn⟩)
instance partialOrder (x : X) : PartialOrder (OpenNhds x) where
  le U V := U.1 ≤ V.1
  le_refl _ := by 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝ : OpenNhds x
⊢ x✝ ≤ x✝

Next tactic:
dsimp [LE.le]
instance partialOrder (x : X) : PartialOrder (OpenNhds x) where
  le U V := U.1 ≤ V.1
  le_refl _ := by dsimp [LE.le]; 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝ : OpenNhds x
⊢ x✝.obj ≤ x✝.obj

Next tactic:
exact le_rfl
instance partialOrder (x : X) : PartialOrder (OpenNhds x) where
  le U V := U.1 ≤ V.1
  le_refl _ := by dsimp [LE.le]; exact le_rfl
  le_trans _ _ _ := by 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝² x✝¹ x✝ : OpenNhds x
⊢ x✝² ≤ x✝¹ → x✝¹ ≤ x✝ → x✝² ≤ x✝

Next tactic:
dsimp [LE.le]
instance partialOrder (x : X) : PartialOrder (OpenNhds x) where
  le U V := U.1 ≤ V.1
  le_refl _ := by dsimp [LE.le]; exact le_rfl
  le_trans _ _ _ := by dsimp [LE.le]; 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝² x✝¹ x✝ : OpenNhds x
⊢ x✝².obj ≤ x✝¹.obj → x✝¹.obj ≤ x✝.obj → x✝².obj ≤ x✝.obj

Next tactic:
exact le_trans
instance (x : X) : OrderTop (OpenNhds x) where
  top := ⟨⊤, trivial⟩
  le_top _ := by 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝ : OpenNhds x
⊢ x✝ ≤ ⊤

Next tactic:
dsimp [LE.le]
instance (x : X) : OrderTop (OpenNhds x) where
  top := ⟨⊤, trivial⟩
  le_top _ := by dsimp [LE.le]; 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
x✝ : OpenNhds x
⊢ x✝.obj ≤ ⊤

Next tactic:
exact le_top
@[simp]
theorem map_id_obj_unop (x : X) (U : (OpenNhds x)ᵒᵖ) : (map (𝟙 X) x).obj (unop U) = unop U := by
  

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : (OpenNhds x)ᵒᵖ
⊢ (map (𝟙 X) x).obj U.unop = U.unop

Next tactic:
simp
@[simp]
theorem op_map_id_obj (x : X) (U : (OpenNhds x)ᵒᵖ) : (map (𝟙 X) x).op.obj U = U := by 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : (OpenNhds x)ᵒᵖ
⊢ (map (𝟙 X) x).op.obj U = U

Next tactic:
simp
/-- `Opens.map f` and `OpenNhds.map f` form a commuting square (up to natural isomorphism)
with the inclusion functors into `Opens X`. -/
def inclusionMapIso (x : X) : inclusion (f x) ⋙ Opens.map f ≅ map f x ⋙ inclusion x :=
  NatIso.ofComponents fun U => by 

Proof state:
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (inclusion (f x) ⋙ Opens.map f).obj U ≅ (map f x ⋙ inclusion x).obj U

Next tactic:
constructor
/-- `Opens.map f` and `OpenNhds.map f` form a commuting square (up to natural isomorphism)
with the inclusion functors into `Opens X`. -/
def inclusionMapIso (x : X) : inclusion (f x) ⋙ Opens.map f ≅ map f x ⋙ inclusion x :=
  NatIso.ofComponents fun U => by constructor; 

Proof state:
case hom_inv_id
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ autoParam (?hom ≫ ?inv = 𝟙 ((inclusion (f x) ⋙ Opens.map f).obj U)) _auto✝
case inv_hom_id
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ autoParam (?inv ≫ ?hom = 𝟙 ((map f x ⋙ inclusion x).obj U)) _auto✝
case hom
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (inclusion (f x) ⋙ Opens.map f).obj U ⟶ (map f x ⋙ inclusion x).obj U
case inv
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (map f x ⋙ inclusion x).obj U ⟶ (inclusion (f x) ⋙ Opens.map f).obj U

Next tactic:
rfl
/-- `Opens.map f` and `OpenNhds.map f` form a commuting square (up to natural isomorphism)
with the inclusion functors into `Opens X`. -/
def inclusionMapIso (x : X) : inclusion (f x) ⋙ Opens.map f ≅ map f x ⋙ inclusion x :=
  NatIso.ofComponents fun U => by constructor; rfl; 

Proof state:
case inv_hom_id
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ autoParam (?inv ≫ ?hom = 𝟙 ((map f x ⋙ inclusion x).obj U)) _auto✝
case hom
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (inclusion (f x) ⋙ Opens.map f).obj U ⟶ (map f x ⋙ inclusion x).obj U
case inv
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (map f x ⋙ inclusion x).obj U ⟶ (inclusion (f x) ⋙ Opens.map f).obj U

Next tactic:
rfl
/-- `Opens.map f` and `OpenNhds.map f` form a commuting square (up to natural isomorphism)
with the inclusion functors into `Opens X`. -/
def inclusionMapIso (x : X) : inclusion (f x) ⋙ Opens.map f ≅ map f x ⋙ inclusion x :=
  NatIso.ofComponents fun U => by constructor; rfl; rfl; 

Proof state:
case hom
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (inclusion (f x) ⋙ Opens.map f).obj U ⟶ (map f x ⋙ inclusion x).obj U
case inv
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (map f x ⋙ inclusion x).obj U ⟶ (inclusion (f x) ⋙ Opens.map f).obj U

Next tactic:
exact 𝟙 _
/-- `Opens.map f` and `OpenNhds.map f` form a commuting square (up to natural isomorphism)
with the inclusion functors into `Opens X`. -/
def inclusionMapIso (x : X) : inclusion (f x) ⋙ Opens.map f ≅ map f x ⋙ inclusion x :=
  NatIso.ofComponents fun U => by constructor; rfl; rfl; exact 𝟙 _; 

Proof state:
case inv
X Y : TopCat
f : X ⟶ Y
x : ↑X
U : OpenNhds (f x)
⊢ (map f x ⋙ inclusion x).obj U ⟶ (inclusion (f x) ⋙ Opens.map f).obj U

Next tactic:
exact 𝟙 _
instance {α ι κ} (C : (ι → Option α) → κ) : Inhabited (ColorFocused C) := by
  

Proof state:
α : Type ?u.3178
ι : Type ?u.3184
κ : Type ?u.3185
C : (ι → Option α) → κ
⊢ Inhabited (ColorFocused C)

Next tactic:
refine' ⟨⟨0, fun _ => none, fun h => _, Multiset.nodup_zero⟩⟩
instance {α ι κ} (C : (ι → Option α) → κ) : Inhabited (ColorFocused C) := by
  refine' ⟨⟨0, fun _ => none, fun h => _, Multiset.nodup_zero⟩⟩
  

Proof state:
α : Type ?u.3178
ι : Type ?u.3184
κ : Type ?u.3185
C : (ι → Option α) → κ
h : AlmostMono C
⊢ h ∈ 0 → (fun x i => Option.getD (idxFun h.line i) x) none = fun x => none

Next tactic:
simp only [Multiset.not_mem_zero, IsEmpty.forall_iff]
/-- A function `f : α → α'` determines a function `line α ι → line α' ι`. For a coordinate `i`,
`l.map f` is the identity at `i` if `l` is, and constantly `f y` if `l` is constantly `y` at `i`. -/
def map {α α' ι} (f : α → α') (l : Line α ι) : Line α' ι where
  idxFun i := (l.idxFun i).map f
  proper := ⟨l.proper.choose, by 

Proof state:
α : Type ?u.3678
α' : Type ?u.3682
ι : Type ?u.3679
f : α → α'
l : Line α ι
⊢ (fun i => Option.map f (idxFun l i)) (Exists.choose (_ : ∃ i, idxFun l i = none)) = none

Next tactic:
simp only [l.proper.choose_spec, Option.map_none']
theorem apply_none {α ι} (l : Line α ι) (x : α) (i : ι) (h : l.idxFun i = none) : l x i = x := by
  

Proof state:
α : Type u_1
ι : Type u_2
l : Line α ι
x : α
i : ι
h : idxFun l i = none
⊢ (fun x i => Option.getD (idxFun l i) x) x i = x

Next tactic:
simp only [Option.getD_none, h, l.apply]
theorem apply_of_ne_none {α ι} (l : Line α ι) (x : α) (i : ι) (h : l.idxFun i ≠ none) :
    some (l x i) = l.idxFun i := by 

Proof state:
α : Type u_1
ι : Type u_2
l : Line α ι
x : α
i : ι
h : idxFun l i ≠ none
⊢ some ((fun x i => Option.getD (idxFun l i) x) x i) = idxFun l i

Next tactic:
rw [l.apply, Option.getD_of_ne_none h]
@[simp]
theorem map_apply {α α' ι} (f : α → α') (l : Line α ι) (x : α) : l.map f (f x) = f ∘ l x := by
  

Proof state:
α : Type u_1
α' : Type u_2
ι : Type u_3
f : α → α'
l : Line α ι
x : α
⊢ (fun x i => Option.getD (idxFun (map f l) i) x) (f x) = f ∘ (fun x i => Option.getD (idxFun l i) x) x

Next tactic:
simp only [Line.apply, Line.map, Option.getD_map]
@[simp]
theorem map_apply {α α' ι} (f : α → α') (l : Line α ι) (x : α) : l.map f (f x) = f ∘ l x := by
  simp only [Line.apply, Line.map, Option.getD_map]
  

Proof state:
α : Type u_1
α' : Type u_2
ι : Type u_3
f : α → α'
l : Line α ι
x : α
⊢ (fun i => f (Option.getD (idxFun l i) x)) = f ∘ fun i => Option.getD (idxFun l i) x

Next tactic:
rfl
@[simp]
theorem vertical_apply {α ι ι'} (v : ι → α) (l : Line α ι') (x : α) :
    l.vertical v x = Sum.elim v (l x) := by
  

Proof state:
α : Type u_1
ι : Type u_2
ι' : Type u_3
v : ι → α
l : Line α ι'
x : α
⊢ (fun x i => Option.getD (idxFun (vertical v l) i) x) x = Sum.elim v ((fun x i => Option.getD (idxFun l i) x) x)

Next tactic:
funext i
@[simp]
theorem vertical_apply {α ι ι'} (v : ι → α) (l : Line α ι') (x : α) :
    l.vertical v x = Sum.elim v (l x) := by
  funext i
  

Proof state:
case h
α : Type u_1
ι : Type u_2
ι' : Type u_3
v : ι → α
l : Line α ι'
x : α
i : ι ⊕ ι'
⊢ (fun x i => Option.getD (idxFun (vertical v l) i) x) x i = Sum.elim v ((fun x i => Option.getD (idxFun l i) x) x) i

Next tactic:
cases i
@[simp]
theorem vertical_apply {α ι ι'} (v : ι → α) (l : Line α ι') (x : α) :
    l.vertical v x = Sum.elim v (l x) := by
  funext i
  cases i <;> 

Proof state:
case h.inl
α : Type u_1
ι : Type u_2
ι' : Type u_3
v : ι → α
l : Line α ι'
x : α
val✝ : ι
⊢ (fun x i => Option.getD (idxFun (vertical v l) i) x) x (Sum.inl val✝) =
    Sum.elim v ((fun x i => Option.getD (idxFun l i) x) x) (Sum.inl val✝)

Next tactic:
rfl
@[simp]
theorem vertical_apply {α ι ι'} (v : ι → α) (l : Line α ι') (x : α) :
    l.vertical v x = Sum.elim v (l x) := by
  funext i
  cases i <;> 

Proof state:
case h.inr
α : Type u_1
ι : Type u_2
ι' : Type u_3
v : ι → α
l : Line α ι'
x : α
val✝ : ι'
⊢ (fun x i => Option.getD (idxFun (vertical v l) i) x) x (Sum.inr val✝) =
    Sum.elim v ((fun x i => Option.getD (idxFun l i) x) x) (Sum.inr val✝)

Next tactic:
rfl
@[simp]
theorem horizontal_apply {α ι ι'} (l : Line α ι) (v : ι' → α) (x : α) :
    l.horizontal v x = Sum.elim (l x) v := by
  

Proof state:
α : Type u_1
ι : Type u_2
ι' : Type u_3
l : Line α ι
v : ι' → α
x : α
⊢ (fun x i => Option.getD (idxFun (horizontal l v) i) x) x = Sum.elim ((fun x i => Option.getD (idxFun l i) x) x) v

Next tactic:
funext i
@[simp]
theorem horizontal_apply {α ι ι'} (l : Line α ι) (v : ι' → α) (x : α) :
    l.horizontal v x = Sum.elim (l x) v := by
  funext i
  

Proof state:
case h
α : Type u_1
ι : Type u_2
ι' : Type u_3
l : Line α ι
v : ι' → α
x : α
i : ι ⊕ ι'
⊢ (fun x i => Option.getD (idxFun (horizontal l v) i) x) x i = Sum.elim ((fun x i => Option.getD (idxFun l i) x) x) v i

Next tactic:
cases i
@[simp]
theorem horizontal_apply {α ι ι'} (l : Line α ι) (v : ι' → α) (x : α) :
    l.horizontal v x = Sum.elim (l x) v := by
  funext i
  cases i <;> 

Proof state:
case h.inl
α : Type u_1
ι : Type u_2
ι' : Type u_3
l : Line α ι
v : ι' → α
x : α
val✝ : ι
⊢ (fun x i => Option.getD (idxFun (horizontal l v) i) x) x (Sum.inl val✝) =
    Sum.elim ((fun x i => Option.getD (idxFun l i) x) x) v (Sum.inl val✝)

Next tactic:
rfl
@[simp]
theorem horizontal_apply {α ι ι'} (l : Line α ι) (v : ι' → α) (x : α) :
    l.horizontal v x = Sum.elim (l x) v := by
  funext i
  cases i <;> 

Proof state:
case h.inr
α : Type u_1
ι : Type u_2
ι' : Type u_3
l : Line α ι
v : ι' → α
x : α
val✝ : ι'
⊢ (fun x i => Option.getD (idxFun (horizontal l v) i) x) x (Sum.inr val✝) =
    Sum.elim ((fun x i => Option.getD (idxFun l i) x) x) v (Sum.inr val✝)

Next tactic:
rfl