l3lab/ntp-mathlib huggingface dataset:
theorem lintegral_prod (κ : kernel α β) [IsSFiniteKernel κ] (η : kernel α γ) [IsSFiniteKernel η]
    (a : α) {g : β × γ → ℝ≥0∞} (hg : Measurable g) :
    ∫⁻ c, g c ∂(κ ×ₖ η) a = ∫⁻ b, ∫⁻ c, g (b, c) ∂η a ∂κ a := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
inst✝¹ : IsSFiniteKernel κ
η : ↥(kernel α γ)
inst✝ : IsSFiniteKernel η
a : α
g : β × γ → ℝ≥0∞
hg : Measurable g
⊢ ∫⁻ (c : β × γ), g c ∂(κ ×ₖ η) a = ∫⁻ (b : β), ∫⁻ (c : γ), g (b, c) ∂η a ∂κ a

Next tactic:
simp_rw [prod, lintegral_compProd _ _ _ hg, swapLeft_apply, prodMkLeft_apply, Prod.swap_prod_mk]
instance IsMarkovKernel.prod (κ : kernel α β) [IsMarkovKernel κ] (η : kernel α γ)
    [IsMarkovKernel η] : IsMarkovKernel (κ ×ₖ η) := by 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
inst✝¹ : IsMarkovKernel κ
η : ↥(kernel α γ)
inst✝ : IsMarkovKernel η
⊢ IsMarkovKernel (κ ×ₖ η)

Next tactic:
rw [kernel.prod]
instance IsMarkovKernel.prod (κ : kernel α β) [IsMarkovKernel κ] (η : kernel α γ)
    [IsMarkovKernel η] : IsMarkovKernel (κ ×ₖ η) := by rw [kernel.prod]; 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
inst✝¹ : IsMarkovKernel κ
η : ↥(kernel α γ)
inst✝ : IsMarkovKernel η
⊢ IsMarkovKernel (κ ⊗ₖ kernel.swapLeft (kernel.prodMkLeft β η))

Next tactic:
infer_instance
instance IsFiniteKernel.prod (κ : kernel α β) [IsFiniteKernel κ] (η : kernel α γ)
    [IsFiniteKernel η] : IsFiniteKernel (κ ×ₖ η) := by 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
inst✝¹ : IsFiniteKernel κ
η : ↥(kernel α γ)
inst✝ : IsFiniteKernel η
⊢ IsFiniteKernel (κ ×ₖ η)

Next tactic:
rw [kernel.prod]
instance IsFiniteKernel.prod (κ : kernel α β) [IsFiniteKernel κ] (η : kernel α γ)
    [IsFiniteKernel η] : IsFiniteKernel (κ ×ₖ η) := by rw [kernel.prod]; 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
inst✝¹ : IsFiniteKernel κ
η : ↥(kernel α γ)
inst✝ : IsFiniteKernel η
⊢ IsFiniteKernel (κ ⊗ₖ kernel.swapLeft (kernel.prodMkLeft β η))

Next tactic:
infer_instance
instance IsSFiniteKernel.prod (κ : kernel α β) (η : kernel α γ) :
    IsSFiniteKernel (κ ×ₖ η) := by 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
η : ↥(kernel α γ)
⊢ IsSFiniteKernel (κ ×ₖ η)

Next tactic:
rw [kernel.prod]
instance IsSFiniteKernel.prod (κ : kernel α β) (η : kernel α γ) :
    IsSFiniteKernel (κ ×ₖ η) := by rw [kernel.prod]; 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
mα : MeasurableSpace α
mβ : MeasurableSpace β
γ : Type u_4
mγ : MeasurableSpace γ
κ : ↥(kernel α β)
η : ↥(kernel α γ)
⊢ IsSFiniteKernel (κ ⊗ₖ kernel.swapLeft (kernel.prodMkLeft β η))

Next tactic:
infer_instance
@[to_additive (attr := aesop safe apply (rule_sets [SetLike]))]
theorem pow_mem {M A} [Monoid M] [SetLike A M] [SubmonoidClass A M] {S : A} {x : M}
    (hx : x ∈ S) : ∀ n : ℕ, x ^ n ∈ S
  | 0 => by
    

Proof state:
M✝ : Type u_1
N : Type u_2
A✝ : Type u_3
inst✝⁴ : MulOneClass M✝
s : Set M✝
inst✝³ : AddZeroClass A✝
t : Set A✝
M : Type u_4
A : Type u_5
inst✝² : Monoid M
inst✝¹ : SetLike A M
inst✝ : SubmonoidClass A M
S : A
x : M
hx : x ∈ S
⊢ x ^ 0 ∈ S

Next tactic:
rw [pow_zero]
@[to_additive (attr := aesop safe apply (rule_sets [SetLike]))]
theorem pow_mem {M A} [Monoid M] [SetLike A M] [SubmonoidClass A M] {S : A} {x : M}
    (hx : x ∈ S) : ∀ n : ℕ, x ^ n ∈ S
  | 0 => by
    rw [pow_zero]
    

Proof state:
M✝ : Type u_1
N : Type u_2
A✝ : Type u_3
inst✝⁴ : MulOneClass M✝
s : Set M✝
inst✝³ : AddZeroClass A✝
t : Set A✝
M : Type u_4
A : Type u_5
inst✝² : Monoid M
inst✝¹ : SetLike A M
inst✝ : SubmonoidClass A M
S : A
x : M
hx : x ∈ S
⊢ 1 ∈ S

Next tactic:
exact OneMemClass.one_mem S
@[to_additive (attr := aesop safe apply (rule_sets [SetLike]))]
theorem pow_mem {M A} [Monoid M] [SetLike A M] [SubmonoidClass A M] {S : A} {x : M}
    (hx : x ∈ S) : ∀ n : ℕ, x ^ n ∈ S
  | 0 => by
    rw [pow_zero]
    exact OneMemClass.one_mem S
  | n + 1 => by
    

Proof state:
M✝ : Type u_1
N : Type u_2
A✝ : Type u_3
inst✝⁴ : MulOneClass M✝
s : Set M✝
inst✝³ : AddZeroClass A✝
t : Set A✝
M : Type u_4
A : Type u_5
inst✝² : Monoid M
inst✝¹ : SetLike A M
inst✝ : SubmonoidClass A M
S : A
x : M
hx : x ∈ S
n : ℕ
⊢ x ^ (n + 1) ∈ S

Next tactic:
rw [pow_succ]
@[to_additive (attr := aesop safe apply (rule_sets [SetLike]))]
theorem pow_mem {M A} [Monoid M] [SetLike A M] [SubmonoidClass A M] {S : A} {x : M}
    (hx : x ∈ S) : ∀ n : ℕ, x ^ n ∈ S
  | 0 => by
    rw [pow_zero]
    exact OneMemClass.one_mem S
  | n + 1 => by
    rw [pow_succ]
    

Proof state:
M✝ : Type u_1
N : Type u_2
A✝ : Type u_3
inst✝⁴ : MulOneClass M✝
s : Set M✝
inst✝³ : AddZeroClass A✝
t : Set A✝
M : Type u_4
A : Type u_5
inst✝² : Monoid M
inst✝¹ : SetLike A M
inst✝ : SubmonoidClass A M
S : A
x : M
hx : x ∈ S
n : ℕ
⊢ x * x ^ n ∈ S

Next tactic:
exact mul_mem hx (pow_mem hx n)
@[to_additive]
instance : SetLike (Submonoid M) M where
  coe s := s.carrier
  coe_injective' p q h := by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
p q : Submonoid M
h : (fun s => s.carrier) p = (fun s => s.carrier) q
⊢ p = q

Next tactic:
cases p
@[to_additive]
instance : SetLike (Submonoid M) M where
  coe s := s.carrier
  coe_injective' p q h := by cases p; 

Proof state:
case mk
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
q : Submonoid M
toSubsemigroup✝ : Subsemigroup M
one_mem'✝ : 1 ∈ toSubsemigroup✝.carrier
h : (fun s => s.carrier) { toSubsemigroup := toSubsemigroup✝, one_mem' := one_mem'✝ } = (fun s => s.carrier) q
⊢ { toSubsemigroup := toSubsemigroup✝, one_mem' := one_mem'✝ } = q

Next tactic:
cases q
@[to_additive]
instance : SetLike (Submonoid M) M where
  coe s := s.carrier
  coe_injective' p q h := by cases p; cases q; 

Proof state:
case mk.mk
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
toSubsemigroup✝¹ : Subsemigroup M
one_mem'✝¹ : 1 ∈ toSubsemigroup✝¹.carrier
toSubsemigroup✝ : Subsemigroup M
one_mem'✝ : 1 ∈ toSubsemigroup✝.carrier
h :
  (fun s => s.carrier) { toSubsemigroup := toSubsemigroup✝¹, one_mem' := one_mem'✝¹ } =
    (fun s => s.carrier) { toSubsemigroup := toSubsemigroup✝, one_mem' := one_mem'✝ }
⊢ { toSubsemigroup := toSubsemigroup✝¹, one_mem' := one_mem'✝¹ } =
    { toSubsemigroup := toSubsemigroup✝, one_mem' := one_mem'✝ }

Next tactic:
congr
@[to_additive]
instance : SetLike (Submonoid M) M where
  coe s := s.carrier
  coe_injective' p q h := by cases p; cases q; congr; 

Proof state:
case mk.mk.e_toSubsemigroup
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
toSubsemigroup✝¹ : Subsemigroup M
one_mem'✝¹ : 1 ∈ toSubsemigroup✝¹.carrier
toSubsemigroup✝ : Subsemigroup M
one_mem'✝ : 1 ∈ toSubsemigroup✝.carrier
h :
  (fun s => s.carrier) { toSubsemigroup := toSubsemigroup✝¹, one_mem' := one_mem'✝¹ } =
    (fun s => s.carrier) { toSubsemigroup := toSubsemigroup✝, one_mem' := one_mem'✝ }
⊢ toSubsemigroup✝¹ = toSubsemigroup✝

Next tactic:
exact SetLike.coe_injective' h
/-- The trivial submonoid `{1}` of a monoid `M`. -/
@[to_additive "The trivial `AddSubmonoid` `{0}` of an `AddMonoid` `M`."]
instance : Bot (Submonoid M) :=
  ⟨{  carrier := {1}
      one_mem' := Set.mem_singleton 1
      mul_mem' := fun ha hb => by
        

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
a✝ b✝ : M
ha : a✝ ∈ {1}
hb : b✝ ∈ {1}
⊢ a✝ * b✝ ∈ {1}

Next tactic:
simp only [Set.mem_singleton_iff] at *
/-- The trivial submonoid `{1}` of a monoid `M`. -/
@[to_additive "The trivial `AddSubmonoid` `{0}` of an `AddMonoid` `M`."]
instance : Bot (Submonoid M) :=
  ⟨{  carrier := {1}
      one_mem' := Set.mem_singleton 1
      mul_mem' := fun ha hb => by
        simp only [Set.mem_singleton_iff] at *
        

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
a✝ b✝ : M
ha : a✝ = 1
hb : b✝ = 1
⊢ a✝ * b✝ = 1

Next tactic:
rw [ha, hb, mul_one]
@[to_additive]
instance : InfSet (Submonoid M) :=
  ⟨fun s =>
    { carrier := ⋂ t ∈ s, ↑t
      one_mem' := Set.mem_biInter fun i _ => i.one_mem
      mul_mem' := fun hx hy =>
        Set.mem_biInter fun i h =>
          i.mul_mem (by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
s : Set (Submonoid M)
a✝ b✝ : M
hx : a✝ ∈ ⋂ t ∈ s, ↑t
hy : b✝ ∈ ⋂ t ∈ s, ↑t
i : Submonoid M
h : i ∈ s
⊢ a✝ ∈ i

Next tactic:
apply Set.mem_iInter₂.1 hx i h
@[to_additive]
instance : InfSet (Submonoid M) :=
  ⟨fun s =>
    { carrier := ⋂ t ∈ s, ↑t
      one_mem' := Set.mem_biInter fun i _ => i.one_mem
      mul_mem' := fun hx hy =>
        Set.mem_biInter fun i h =>
          i.mul_mem (by apply Set.mem_iInter₂.1 hx i h) (by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
s : Set (Submonoid M)
a✝ b✝ : M
hx : a✝ ∈ ⋂ t ∈ s, ↑t
hy : b✝ ∈ ⋂ t ∈ s, ↑t
i : Submonoid M
h : i ∈ s
⊢ b✝ ∈ i

Next tactic:
apply Set.mem_iInter₂.1 hy i h
@[to_additive]
theorem mem_iInf {ι : Sort*} {S : ι → Submonoid M} {x : M} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S✝ : Submonoid M
ι : Sort u_4
S : ι → Submonoid M
x : M
⊢ x ∈ ⨅ i, S i ↔ ∀ (i : ι), x ∈ S i

Next tactic:
simp only [iInf, mem_sInf, Set.forall_range_iff]
@[to_additive (attr := simp, norm_cast)]
theorem coe_iInf {ι : Sort*} {S : ι → Submonoid M} : (↑(⨅ i, S i) : Set M) = ⋂ i, S i := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S✝ : Submonoid M
ι : Sort u_4
S : ι → Submonoid M
⊢ ↑(⨅ i, S i) = ⋂ i, ↑(S i)

Next tactic:
simp only [iInf, coe_sInf, Set.biInter_range]
@[to_additive (attr := simp)]
theorem subsingleton_iff : Subsingleton (Submonoid M) ↔ Subsingleton M :=
  ⟨fun h =>
    ⟨fun x y =>
      have : ∀ i : M, i = 1 := fun i =>
        mem_bot.mp <| Subsingleton.elim (⊤ : Submonoid M) ⊥ ▸ mem_top i
      (this x).trans (this y).symm⟩,
    fun h =>
    ⟨fun x y => Submonoid.ext fun i => Subsingleton.elim 1 i ▸ by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
h : Subsingleton M
x y : Submonoid M
i : M
⊢ 1 ∈ x ↔ 1 ∈ y

Next tactic:
simp [Submonoid.one_mem]
/-- A dependent version of `Submonoid.closure_induction`.  -/
@[to_additive (attr := elab_as_elim) "A dependent version of `AddSubmonoid.closure_induction`. "]
theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop}
    (Hs : ∀ (x) (h : x ∈ s), p x (subset_closure h)) (H1 : p 1 (one_mem _))
    (Hmul : ∀ x hx y hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) {x} (hx : x ∈ closure s) :
    p x hx := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
s : Set M
p : (x : M) → x ∈ closure s → Prop
Hs : ∀ (x : M) (h : x ∈ s), p x (_ : x ∈ ↑(closure s))
H1 : p 1 (_ : 1 ∈ closure s)
Hmul : ∀ (x : M) (hx : x ∈ closure s) (y : M) (hy : y ∈ closure s), p x hx → p y hy → p (x * y) (_ : x * y ∈ closure s)
x : M
hx : x ∈ closure s
⊢ p x hx

Next tactic:
refine' Exists.elim _ fun (hx : x ∈ closure s) (hc : p x hx) => hc
/-- A dependent version of `Submonoid.closure_induction`.  -/
@[to_additive (attr := elab_as_elim) "A dependent version of `AddSubmonoid.closure_induction`. "]
theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop}
    (Hs : ∀ (x) (h : x ∈ s), p x (subset_closure h)) (H1 : p 1 (one_mem _))
    (Hmul : ∀ x hx y hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) {x} (hx : x ∈ closure s) :
    p x hx := by
  refine' Exists.elim _ fun (hx : x ∈ closure s) (hc : p x hx) => hc
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
s : Set M
p : (x : M) → x ∈ closure s → Prop
Hs : ∀ (x : M) (h : x ∈ s), p x (_ : x ∈ ↑(closure s))
H1 : p 1 (_ : 1 ∈ closure s)
Hmul : ∀ (x : M) (hx : x ∈ closure s) (y : M) (hy : y ∈ closure s), p x hx → p y hy → p (x * y) (_ : x * y ∈ closure s)
x : M
hx : x ∈ closure s
⊢ ∃ (x_1 : x ∈ closure s), p x x_1

Next tactic:
exact
    closure_induction hx (fun x hx => ⟨_, Hs x hx⟩) ⟨_, H1⟩ fun x y ⟨hx', hx⟩ ⟨hy', hy⟩ =>
      ⟨_, Hmul _ _ _ _ hx hy⟩
/-- If `s` is a dense set in a monoid `M`, `Submonoid.closure s = ⊤`, then in order to prove that
some predicate `p` holds for all `x : M` it suffices to verify `p x` for `x ∈ s`, verify `p 1`,
and verify that `p x` and `p y` imply `p (x * y)`. -/
@[to_additive (attr := elab_as_elim)
      "If `s` is a dense set in an additive monoid `M`, `AddSubmonoid.closure s = ⊤`, then in
      order to prove that some predicate `p` holds for all `x : M` it suffices to verify `p x` for
      `x ∈ s`, verify `p 0`, and verify that `p x` and `p y` imply `p (x + y)`."]
theorem dense_induction {p : M → Prop} (x : M) {s : Set M} (hs : closure s = ⊤) (Hs : ∀ x ∈ s, p x)
    (H1 : p 1) (Hmul : ∀ x y, p x → p y → p (x * y)) : p x := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
p : M → Prop
x : M
s : Set M
hs : closure s = ⊤
Hs : ∀ x ∈ s, p x
H1 : p 1
Hmul : ∀ (x y : M), p x → p y → p (x * y)
⊢ p x

Next tactic:
have : ∀ x ∈ closure s, p x := fun x hx => closure_induction hx Hs H1 Hmul
/-- If `s` is a dense set in a monoid `M`, `Submonoid.closure s = ⊤`, then in order to prove that
some predicate `p` holds for all `x : M` it suffices to verify `p x` for `x ∈ s`, verify `p 1`,
and verify that `p x` and `p y` imply `p (x * y)`. -/
@[to_additive (attr := elab_as_elim)
      "If `s` is a dense set in an additive monoid `M`, `AddSubmonoid.closure s = ⊤`, then in
      order to prove that some predicate `p` holds for all `x : M` it suffices to verify `p x` for
      `x ∈ s`, verify `p 0`, and verify that `p x` and `p y` imply `p (x + y)`."]
theorem dense_induction {p : M → Prop} (x : M) {s : Set M} (hs : closure s = ⊤) (Hs : ∀ x ∈ s, p x)
    (H1 : p 1) (Hmul : ∀ x y, p x → p y → p (x * y)) : p x := by
  have : ∀ x ∈ closure s, p x := fun x hx => closure_induction hx Hs H1 Hmul
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s✝ : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
p : M → Prop
x : M
s : Set M
hs : closure s = ⊤
Hs : ∀ x ∈ s, p x
H1 : p 1
Hmul : ∀ (x y : M), p x → p y → p (x * y)
this : ∀ x ∈ closure s, p x
⊢ p x

Next tactic:
simpa [hs] using this x
@[to_additive]
theorem sup_eq_closure (N N' : Submonoid M) : N ⊔ N' = closure ((N : Set M) ∪ (N' : Set M)) := by
  

Proof state:
M : Type u_1
N✝ : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S N N' : Submonoid M
⊢ N ⊔ N' = closure (↑N ∪ ↑N')

Next tactic:
simp_rw [closure_union, closure_eq]
@[to_additive]
theorem closure_singleton_le_iff_mem (m : M) (p : Submonoid M) : closure {m} ≤ p ↔ m ∈ p := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
m : M
p : Submonoid M
⊢ closure {m} ≤ p ↔ m ∈ p

Next tactic:
rw [closure_le, singleton_subset_iff, SetLike.mem_coe]
@[to_additive]
theorem mem_iSup {ι : Sort*} (p : ι → Submonoid M) {m : M} :
    (m ∈ ⨆ i, p i) ↔ ∀ N, (∀ i, p i ≤ N) → m ∈ N := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
ι : Sort u_4
p : ι → Submonoid M
m : M
⊢ m ∈ ⨆ i, p i ↔ ∀ (N : Submonoid M), (∀ (i : ι), p i ≤ N) → m ∈ N

Next tactic:
rw [← closure_singleton_le_iff_mem, le_iSup_iff]
@[to_additive]
theorem mem_iSup {ι : Sort*} (p : ι → Submonoid M) {m : M} :
    (m ∈ ⨆ i, p i) ↔ ∀ N, (∀ i, p i ≤ N) → m ∈ N := by
  rw [← closure_singleton_le_iff_mem, le_iSup_iff]
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
ι : Sort u_4
p : ι → Submonoid M
m : M
⊢ (∀ (b : Submonoid M), (∀ (i : ι), p i ≤ b) → closure {m} ≤ b) ↔ ∀ (N : Submonoid M), (∀ (i : ι), p i ≤ N) → m ∈ N

Next tactic:
simp only [closure_singleton_le_iff_mem]
@[to_additive]
theorem iSup_eq_closure {ι : Sort*} (p : ι → Submonoid M) :
    ⨆ i, p i = Submonoid.closure (⋃ i, (p i : Set M)) := by
  

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S : Submonoid M
ι : Sort u_4
p : ι → Submonoid M
⊢ ⨆ i, p i = closure (⋃ i, ↑(p i))

Next tactic:
simp_rw [Submonoid.closure_iUnion, Submonoid.closure_eq]
@[to_additive]
theorem disjoint_def {p₁ p₂ : Submonoid M} : Disjoint p₁ p₂ ↔ ∀ {x : M}, x ∈ p₁ → x ∈ p₂ → x = 1 :=
  by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝¹ : MulOneClass M
s : Set M
inst✝ : AddZeroClass A
t : Set A
S p₁ p₂ : Submonoid M
⊢ Disjoint p₁ p₂ ↔ ∀ {x : M}, x ∈ p₁ → x ∈ p₂ → x = 1

Next tactic:
simp_rw [disjoint_iff_inf_le, SetLike.le_def, mem_inf, and_imp, mem_bot]
/-- The submonoid of elements `x : M` such that `f x = g x` -/
@[to_additive "The additive submonoid of elements `x : M` such that `f x = g x`"]
def eqLocusM (f g : M →* N) : Submonoid M where
  carrier := { x | f x = g x }
  one_mem' := by rw [Set.mem_setOf_eq, f.map_one, g.map_one]
  mul_mem' (hx : _ = _) (hy : _ = _) := by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝² : MulOneClass M
s : Set M
inst✝¹ : AddZeroClass A
t : Set A
inst✝ : MulOneClass N
f g : M →* N
a✝ b✝ : M
hx : f a✝ = g a✝
hy : f b✝ = g b✝
⊢ a✝ * b✝ ∈ {x | f x = g x}

Next tactic:
simp [*]
/-- The submonoid of elements `x : M` such that `f x = g x` -/
@[to_additive "The additive submonoid of elements `x : M` such that `f x = g x`"]
def eqLocusM (f g : M →* N) : Submonoid M where
  carrier := { x | f x = g x }
  one_mem' := by 

Proof state:
M : Type u_1
N : Type u_2
A : Type u_3
inst✝² : MulOneClass M
s : Set M
inst✝¹ : AddZeroClass A
t : Set A
inst✝ : MulOneClass N
f g : M →* N
⊢ 1 ∈
    { carrier := {x | f x = g x}, mul_mem' := (_ : ∀ {a b : M}, f a = g a → f b = g b → f (a * b) = g (a * b)) }.carrier

Next tactic:
rw [Set.mem_setOf_eq, f.map_one, g.map_one]
/-- The submonoid consisting of the units of a monoid -/
@[to_additive "The additive submonoid consisting of the additive units of an additive monoid"]
def IsUnit.submonoid (M : Type*) [Monoid M] : Submonoid M where
  carrier := setOf IsUnit
  one_mem' := by simp only [isUnit_one, Set.mem_setOf_eq]
  mul_mem' := by
    

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
⊢ ∀ {a b : M}, a ∈ setOf IsUnit → b ∈ setOf IsUnit → a * b ∈ setOf IsUnit

Next tactic:
intro a b ha hb
/-- The submonoid consisting of the units of a monoid -/
@[to_additive "The additive submonoid consisting of the additive units of an additive monoid"]
def IsUnit.submonoid (M : Type*) [Monoid M] : Submonoid M where
  carrier := setOf IsUnit
  one_mem' := by simp only [isUnit_one, Set.mem_setOf_eq]
  mul_mem' := by
    intro a b ha hb
    

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
a b : M
ha : a ∈ setOf IsUnit
hb : b ∈ setOf IsUnit
⊢ a * b ∈ setOf IsUnit

Next tactic:
rw [Set.mem_setOf_eq] at *
/-- The submonoid consisting of the units of a monoid -/
@[to_additive "The additive submonoid consisting of the additive units of an additive monoid"]
def IsUnit.submonoid (M : Type*) [Monoid M] : Submonoid M where
  carrier := setOf IsUnit
  one_mem' := by simp only [isUnit_one, Set.mem_setOf_eq]
  mul_mem' := by
    intro a b ha hb
    rw [Set.mem_setOf_eq] at *
    

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
a b : M
ha : IsUnit a
hb : IsUnit b
⊢ IsUnit (a * b)

Next tactic:
exact IsUnit.mul ha hb
/-- The submonoid consisting of the units of a monoid -/
@[to_additive "The additive submonoid consisting of the additive units of an additive monoid"]
def IsUnit.submonoid (M : Type*) [Monoid M] : Submonoid M where
  carrier := setOf IsUnit
  one_mem' := by 

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
⊢ 1 ∈
    { carrier := setOf IsUnit,
        mul_mem' := (_ : ∀ {a b : M}, a ∈ setOf IsUnit → b ∈ setOf IsUnit → a * b ∈ setOf IsUnit) }.carrier

Next tactic:
simp only [isUnit_one, Set.mem_setOf_eq]
@[to_additive]
theorem IsUnit.mem_submonoid_iff {M : Type*} [Monoid M] (a : M) :
    a ∈ IsUnit.submonoid M ↔ IsUnit a := by
  

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
a : M
⊢ a ∈ submonoid M ↔ IsUnit a

Next tactic:
change a ∈ setOf IsUnit ↔ IsUnit a
@[to_additive]
theorem IsUnit.mem_submonoid_iff {M : Type*} [Monoid M] (a : M) :
    a ∈ IsUnit.submonoid M ↔ IsUnit a := by
  change a ∈ setOf IsUnit ↔ IsUnit a
  

Proof state:
M✝ : Type u_1
N : Type u_2
A : Type u_3
inst✝² : Monoid M✝
inst✝¹ : Monoid N
s : Set M✝
M : Type u_4
inst✝ : Monoid M
a : M
⊢ a ∈ setOf IsUnit ↔ IsUnit a

Next tactic:
rw [Set.mem_setOf_eq]
/-- Let `s` be a subset of a monoid `M` such that the closure of `s` is the whole monoid.
Then `MonoidHom.ofClosureEqTopLeft` defines a monoid homomorphism from `M` asking for
a proof of `f (x * y) = f x * f y` only for `x ∈ s`. -/
@[to_additive
      "Let `s` be a subset of an additive monoid `M` such that the closure of `s` is
      the whole monoid. Then `AddMonoidHom.ofClosureEqTopLeft` defines an additive monoid
      homomorphism from `M` asking for a proof of `f (x + y) = f x + f y` only for `x ∈ s`. "]
def ofClosureMEqTopLeft {M N} [Monoid M] [Monoid N] {s : Set M} (f : M → N) (hs : closure s = ⊤)
    (h1 : f 1 = 1) (hmul : ∀ x ∈ s, ∀ (y), f (x * y) = f x * f y) :
    M →* N where
  toFun := f
  map_one' := h1
  map_mul' x :=
    (dense_induction (p := _) x hs hmul fun y => by 

Proof state:
M✝ : Type u_1
N✝ : Type u_2
A : Type u_3
inst✝³ : Monoid M✝
inst✝² : Monoid N✝
s✝ : Set M✝
M : Type ?u.36463
N : Type ?u.36466
inst✝¹ : Monoid M
inst✝ : Monoid N
s : Set M
f : M → N
hs : closure s = ⊤
h1 : f 1 = 1
hmul : ∀ x ∈ s, ∀ (y : M), f (x * y) = f x * f y
x y : M
⊢ f (1 * y) = f 1 * f y

Next tactic:
rw [one_mul, h1, one_mul]
/-- Let `s` be a subset of a monoid `M` such that the closure of `s` is the whole monoid.
Then `MonoidHom.ofClosureEqTopLeft` defines a monoid homomorphism from `M` asking for
a proof of `f (x * y) = f x * f y` only for `x ∈ s`. -/
@[to_additive
      "Let `s` be a subset of an additive monoid `M` such that the closure of `s` is
      the whole monoid. Then `AddMonoidHom.ofClosureEqTopLeft` defines an additive monoid
      homomorphism from `M` asking for a proof of `f (x + y) = f x + f y` only for `x ∈ s`. "]
def ofClosureMEqTopLeft {M N} [Monoid M] [Monoid N] {s : Set M} (f : M → N) (hs : closure s = ⊤)
    (h1 : f 1 = 1) (hmul : ∀ x ∈ s, ∀ (y), f (x * y) = f x * f y) :
    M →* N where
  toFun := f
  map_one' := h1
  map_mul' x :=
    (dense_induction (p := _) x hs hmul fun y => by rw [one_mul, h1, one_mul]) fun a b ha hb y => by
      

Proof state:
M✝ : Type u_1
N✝ : Type u_2
A : Type u_3
inst✝³ : Monoid M✝
inst✝² : Monoid N✝
s✝ : Set M✝
M : Type ?u.36463
N : Type ?u.36466
inst✝¹ : Monoid M
inst✝ : Monoid N
s : Set M
f : M → N
hs : closure s = ⊤
h1 : f 1 = 1
hmul : ∀ x ∈ s, ∀ (y : M), f (x * y) = f x * f y
x a b : M
ha : ∀ (y : M), f (a * y) = f a * f y
hb : ∀ (y : M), f (b * y) = f b * f y
y : M
⊢ f (a * b * y) = f (a * b) * f y

Next tactic:
rw [mul_assoc, ha, ha, hb, mul_assoc]