l3lab/ntp-mathlib huggingface dataset:
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      

Proof state:
case mp.right.intro.intro.a
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
h : prod s t ≤ u
x : N
hx : x ∈ ↑t
⊢ (inr M N) x ∈ prod s t

Next tactic:
exact ⟨Submonoid.one_mem _, hx⟩
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · 

Proof state:
case mpr
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
⊢ map (inl M N) s ≤ u ∧ map (inr M N) t ≤ u → prod s t ≤ u

Next tactic:
rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    

Proof state:
case mpr.intro.mk.intro
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
⊢ (x1, x2) ∈ u

Next tactic:
have h1' : inl M N x1 ∈ u := by
      apply hH
      simpa using h1
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
⊢ (inl M N) x1 ∈ u

Next tactic:
apply hH
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      apply hH
      

Proof state:
case a
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
⊢ (inl M N) x1 ∈ map (inl M N) s

Next tactic:
simpa using h1
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      apply hH
      simpa using h1
    

Proof state:
case mpr.intro.mk.intro
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
h1' : (inl M N) x1 ∈ u
⊢ (x1, x2) ∈ u

Next tactic:
have h2' : inr M N x2 ∈ u := by
      apply hK
      simpa using h2
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      apply hH
      simpa using h1
    have h2' : inr M N x2 ∈ u := by
      

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
h1' : (inl M N) x1 ∈ u
⊢ (inr M N) x2 ∈ u

Next tactic:
apply hK
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      apply hH
      simpa using h1
    have h2' : inr M N x2 ∈ u := by
      apply hK
      

Proof state:
case a
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
h1' : (inl M N) x1 ∈ u
⊢ (inr M N) x2 ∈ map (inr M N) t

Next tactic:
simpa using h2
@[to_additive prod_le_iff]
theorem prod_le_iff {s : Submonoid M} {t : Submonoid N} {u : Submonoid (M × N)} :
    s.prod t ≤ u ↔ s.map (inl M N) ≤ u ∧ t.map (inr M N) ≤ u := by
  constructor
  · intro h
    constructor
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨hx, Submonoid.one_mem _⟩
    · rintro _ ⟨x, hx, rfl⟩
      apply h
      exact ⟨Submonoid.one_mem _, hx⟩
  · rintro ⟨hH, hK⟩ ⟨x1, x2⟩ ⟨h1, h2⟩
    have h1' : inl M N x1 ∈ u := by
      apply hH
      simpa using h1
    have h2' : inr M N x2 ∈ u := by
      apply hK
      simpa using h2
    

Proof state:
case mpr.intro.mk.intro
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
u : Submonoid (M × N)
hH : map (inl M N) s ≤ u
hK : map (inr M N) t ≤ u
x1 : M
x2 : N
h1 : (x1, x2).1 ∈ ↑s
h2 : (x1, x2).2 ∈ ↑t
h1' : (inl M N) x1 ∈ u
h2' : (inr M N) x2 ∈ u
⊢ (x1, x2) ∈ u

Next tactic:
simpa using Submonoid.mul_mem _ h1' h2'
@[to_additive]
theorem map_mrange (g : N →* P) (f : M →* N) : f.mrange.map g = mrange (comp g f) := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
g : N →* P
f : M →* N
⊢ map g (mrange f) = mrange (comp g f)

Next tactic:
simpa only [mrange_eq_map] using (⊤ : Submonoid M).map_map g f
@[to_additive]
theorem mrange_top_iff_surjective {f : F} : mrange f = (⊤ : Submonoid N) ↔ Function.Surjective f :=
  SetLike.ext'_iff.trans <| Iff.trans (by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : F
⊢ ↑(mrange f) = ↑⊤ ↔ Set.range ⇑f = Set.univ

Next tactic:
rw [coe_mrange, coe_top]
@[to_additive (attr := simp)]
theorem restrict_mrange (f : M →* N) : mrange (f.restrict S) = S.map f := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
⊢ mrange (restrict f S) = map f S

Next tactic:
simp [SetLike.ext_iff]
@[to_additive]
theorem mrangeRestrict_mker (f : M →* N) : mker (mrangeRestrict f) = mker f := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
⊢ mker (mrangeRestrict f) = mker f

Next tactic:
ext x
@[to_additive]
theorem mrangeRestrict_mker (f : M →* N) : mker (mrangeRestrict f) = mker f := by
  ext x
  

Proof state:
case h
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
x : M
⊢ x ∈ mker (mrangeRestrict f) ↔ x ∈ mker f

Next tactic:
change (⟨f x, _⟩ : mrange f) = ⟨1, _⟩ ↔ f x = 1
@[to_additive]
theorem mrangeRestrict_mker (f : M →* N) : mker (mrangeRestrict f) = mker f := by
  ext x
  change (⟨f x, _⟩ : mrange f) = ⟨1, _⟩ ↔ f x = 1
  

Proof state:
case h
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
x : M
⊢ { val := f x, property := (_ : ∃ y, f y = f x) } = { val := 1, property := (_ : 1 ∈ mrange f) } ↔ f x = 1

Next tactic:
simp
@[to_additive (attr := simp)]
theorem mker_one : mker (1 : M →* N) = ⊤ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
⊢ mker 1 = ⊤

Next tactic:
ext
@[to_additive (attr := simp)]
theorem mker_one : mker (1 : M →* N) = ⊤ := by
  ext
  

Proof state:
case h
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
x✝ : M
⊢ x✝ ∈ mker 1 ↔ x✝ ∈ ⊤

Next tactic:
simp [mem_mker]
@[to_additive mker_prod_map]
theorem mker_prod_map {M' : Type*} {N' : Type*} [MulOneClass M'] [MulOneClass N'] (f : M →* N)
    (g : M' →* N') : mker (prodMap f g) = f.mker.prod (mker g) := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝⁵ : MulOneClass M
inst✝⁴ : MulOneClass N
inst✝³ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝² : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
M' : Type u_6
N' : Type u_7
inst✝¹ : MulOneClass M'
inst✝ : MulOneClass N'
f : M →* N
g : M' →* N'
⊢ mker (prodMap f g) = prod (mker f) (mker g)

Next tactic:
rw [← comap_bot', ← comap_bot', ← comap_bot', ← prod_map_comap_prod', bot_prod_bot]
@[to_additive (attr := simp)]
theorem mker_inl : mker (inl M N) = ⊥ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
⊢ mker (inl M N) = ⊥

Next tactic:
ext x
@[to_additive (attr := simp)]
theorem mker_inl : mker (inl M N) = ⊥ := by
  ext x
  

Proof state:
case h
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
x : M
⊢ x ∈ mker (inl M N) ↔ x ∈ ⊥

Next tactic:
simp [mem_mker]
@[to_additive (attr := simp)]
theorem mker_inr : mker (inr M N) = ⊥ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
⊢ mker (inr M N) = ⊥

Next tactic:
ext x
@[to_additive (attr := simp)]
theorem mker_inr : mker (inr M N) = ⊥ := by
  ext x
  

Proof state:
case h
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
x : N
⊢ x ∈ mker (inr M N) ↔ x ∈ ⊥

Next tactic:
simp [mem_mker]
@[to_additive]
theorem submonoidMap_surjective (f : M →* N) (M' : Submonoid M) :
    Function.Surjective (f.submonoidMap M') := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
M' : Submonoid M
⊢ Function.Surjective ⇑(submonoidMap f M')

Next tactic:
rintro ⟨_, x, hx, rfl⟩
@[to_additive]
theorem submonoidMap_surjective (f : M →* N) (M' : Submonoid M) :
    Function.Surjective (f.submonoidMap M') := by
  rintro ⟨_, x, hx, rfl⟩
  

Proof state:
case mk.intro.intro
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
F : Type u_5
mc : MonoidHomClass F M N
f : M →* N
M' : Submonoid M
x : M
hx : x ∈ ↑M'
⊢ ∃ a, (submonoidMap f M') a = { val := f x, property := (_ : ∃ a ∈ ↑M', f a = f x) }

Next tactic:
exact ⟨⟨x, hx⟩, rfl⟩
@[to_additive]
theorem mrange_inl : mrange (inl M N) = prod ⊤ ⊥ := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
⊢ mrange (inl M N) = prod ⊤ ⊥

Next tactic:
simpa only [mrange_eq_map] using map_inl ⊤
@[to_additive]
theorem mrange_inr : mrange (inr M N) = prod ⊥ ⊤ := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
⊢ mrange (inr M N) = prod ⊥ ⊤

Next tactic:
simpa only [mrange_eq_map] using map_inr ⊤
@[to_additive prod_eq_bot_iff]
theorem prod_eq_bot_iff {s : Submonoid M} {t : Submonoid N} : s.prod t = ⊥ ↔ s = ⊥ ∧ t = ⊥ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
⊢ prod s t = ⊥ ↔ s = ⊥ ∧ t = ⊥

Next tactic:
simp only [eq_bot_iff, prod_le_iff, (gc_map_comap _).le_iff_le, comap_bot', mker_inl, mker_inr]
@[to_additive prod_eq_top_iff]
theorem prod_eq_top_iff {s : Submonoid M} {t : Submonoid N} : s.prod t = ⊤ ↔ s = ⊤ ∧ t = ⊤ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
s : Submonoid M
t : Submonoid N
⊢ prod s t = ⊤ ↔ s = ⊤ ∧ t = ⊤

Next tactic:
simp only [eq_top_iff, le_prod_iff, ← (gc_map_comap _).le_iff_le, ← mrange_eq_map, mrange_fst,
    mrange_snd]
@[to_additive (attr := simp)]
theorem mrange_inl_sup_mrange_inr : mrange (inl M N) ⊔ mrange (inr M N) = ⊤ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
⊢ mrange (inl M N) ⊔ mrange (inr M N) = ⊤

Next tactic:
simp only [mrange_inl, mrange_inr, prod_bot_sup_bot_prod, top_prod_top]
@[to_additive]
theorem eq_bot_iff_forall : S = ⊥ ↔ ∀ x ∈ S, x = (1 : M) :=
  SetLike.ext_iff.trans <| by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
⊢ (∀ (x : M), x ∈ S ↔ x ∈ ⊥) ↔ ∀ x ∈ S, x = 1

Next tactic:
simp (config := { contextual := true }) [iff_def, S.one_mem]
@[to_additive]
theorem eq_bot_of_subsingleton [Subsingleton S] : S = ⊥ := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝¹ : SetLike A M
hA : SubmonoidClass A M
S' : A
inst✝ : Subsingleton ↥S
⊢ S = ⊥

Next tactic:
rw [eq_bot_iff_forall]
@[to_additive]
theorem eq_bot_of_subsingleton [Subsingleton S] : S = ⊥ := by
  rw [eq_bot_iff_forall]
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝¹ : SetLike A M
hA : SubmonoidClass A M
S' : A
inst✝ : Subsingleton ↥S
⊢ ∀ x ∈ S, x = 1

Next tactic:
intro y hy
@[to_additive]
theorem eq_bot_of_subsingleton [Subsingleton S] : S = ⊥ := by
  rw [eq_bot_iff_forall]
  intro y hy
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝¹ : SetLike A M
hA : SubmonoidClass A M
S' : A
inst✝ : Subsingleton ↥S
y : M
hy : y ∈ S
⊢ y = 1

Next tactic:
simpa using _root_.congr_arg ((↑) : S → M) <| Subsingleton.elim (⟨y, hy⟩ : S) 1
@[to_additive]
theorem nontrivial_iff_exists_ne_one (S : Submonoid M) : Nontrivial S ↔ ∃ x ∈ S, x ≠ (1 : M) :=
  calc
    Nontrivial S ↔ ∃ x : S, x ≠ 1 := nontrivial_iff_exists_ne 1
    _ ↔ ∃ (x : _) (hx : x ∈ S), (⟨x, hx⟩ : S) ≠ ⟨1, S.one_mem⟩ := Subtype.exists
    _ ↔ ∃ x ∈ S, x ≠ (1 : M) := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S✝ : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
S : Submonoid M
⊢ (∃ x, ∃ (hx : x ∈ S), { val := x, property := hx } ≠ { val := 1, property := (_ : 1 ∈ S) }) ↔ ∃ x ∈ S, x ≠ 1

Next tactic:
simp [Ne.def]
/-- A submonoid is either the trivial submonoid or nontrivial. -/
@[to_additive "An additive submonoid is either the trivial additive submonoid or nontrivial."]
theorem bot_or_nontrivial (S : Submonoid M) : S = ⊥ ∨ Nontrivial S := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S✝ : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
S : Submonoid M
⊢ S = ⊥ ∨ Nontrivial ↥S

Next tactic:
simp only [eq_bot_iff_forall, nontrivial_iff_exists_ne_one, ← not_forall, ← not_imp, Classical.em]
/-- A monoid homomorphism `f : M →* N` with a left-inverse `g : N → M` defines a multiplicative
equivalence between `M` and `f.mrange`.
This is a bidirectional version of `MonoidHom.mrange_restrict`. -/
@[to_additive (attr := simps (config := { simpRhs := true }))
      "An additive monoid homomorphism `f : M →+ N` with a left-inverse `g : N → M`
      defines an additive equivalence between `M` and `f.mrange`.
      This is a bidirectional version of `AddMonoidHom.mrange_restrict`. "]
def ofLeftInverse' (f : M →* N) {g : N → M} (h : Function.LeftInverse g f) :
    M ≃* MonoidHom.mrange f :=
  { f.mrangeRestrict with
    toFun := f.mrangeRestrict
    invFun := g ∘ f.mrange.subtype
    left_inv := h
    right_inv := fun x =>
      Subtype.ext <|
        let ⟨x', hx'⟩ := MonoidHom.mem_mrange.mp x.2
        show f (g x) = x by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
T : Submonoid M
f : M →* N
g : N → M
h : Function.LeftInverse g ⇑f
src✝ : M →* ↥(MonoidHom.mrange f) := MonoidHom.mrangeRestrict f
x : ↥(MonoidHom.mrange f)
x' : M
hx' : f x' = ↑x
⊢ f (g ↑x) = ↑x

Next tactic:
rw [← hx', h x']
@[to_additive (attr := simp)]
theorem Submonoid.equivMapOfInjective_coe_mulEquiv (e : M ≃* N) :
    S.equivMapOfInjective (e : M →* N) (EquivLike.injective e) = e.submonoidMap S := by
  

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
e : M ≃* N
⊢ equivMapOfInjective S ↑e (_ : Function.Injective ⇑e) = MulEquiv.submonoidMap e S

Next tactic:
ext
@[to_additive (attr := simp)]
theorem Submonoid.equivMapOfInjective_coe_mulEquiv (e : M ≃* N) :
    S.equivMapOfInjective (e : M →* N) (EquivLike.injective e) = e.submonoidMap S := by
  ext
  

Proof state:
case h.a
M : Type u_1
N : Type u_2
P : Type u_3
inst✝³ : MulOneClass M
inst✝² : MulOneClass N
inst✝¹ : MulOneClass P
S : Submonoid M
A : Type u_4
inst✝ : SetLike A M
hA : SubmonoidClass A M
S' : A
e : M ≃* N
x✝ : ↥S
⊢ ↑((equivMapOfInjective S ↑e (_ : Function.Injective ⇑e)) x✝) = ↑((MulEquiv.submonoidMap e S) x✝)

Next tactic:
rfl
example {S : Submonoid M'} : IsScalarTower S M' M' := by 

Proof state:
M : Type u_1
N : Type u_2
P : Type u_3
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass P
S✝ : Submonoid M
A : Type u_4
inst✝¹ : SetLike A M
hA : SubmonoidClass A M
S' : A
M' : Type u_5
α : Type u_6
β : Type u_7
inst✝ : Monoid M'
S : Submonoid M'
⊢ IsScalarTower (↥S) M' M'

Next tactic:
infer_instance
/-- A Lebesgue Integral from -∞ to y can be expressed as the sum of one from -∞ to 0 and 0 to x -/
lemma lintegral_Iic_eq_lintegral_Iio_add_Icc {y z : ℝ} (f : ℝ → ℝ≥0∞) (hzy : z ≤ y) :
    ∫⁻ x in Iic y, f x = (∫⁻ x in Iio z, f x) + ∫⁻ x in Icc z y, f x := by
  

Proof state:
y z : ℝ
f : ℝ → ℝ≥0∞
hzy : z ≤ y
⊢ ∫⁻ (x : ℝ) in Iic y, f x = (∫⁻ (x : ℝ) in Iio z, f x) + ∫⁻ (x : ℝ) in Icc z y, f x

Next tactic:
rw [← Iio_union_Icc_eq_Iic hzy, lintegral_union measurableSet_Icc]
/-- A Lebesgue Integral from -∞ to y can be expressed as the sum of one from -∞ to 0 and 0 to x -/
lemma lintegral_Iic_eq_lintegral_Iio_add_Icc {y z : ℝ} (f : ℝ → ℝ≥0∞) (hzy : z ≤ y) :
    ∫⁻ x in Iic y, f x = (∫⁻ x in Iio z, f x) + ∫⁻ x in Icc z y, f x := by
  rw [← Iio_union_Icc_eq_Iic hzy, lintegral_union measurableSet_Icc]
  

Proof state:
y z : ℝ
f : ℝ → ℝ≥0∞
hzy : z ≤ y
⊢ Disjoint (Iio z) (Icc z y)

Next tactic:
rw [Set.disjoint_iff]
/-- A Lebesgue Integral from -∞ to y can be expressed as the sum of one from -∞ to 0 and 0 to x -/
lemma lintegral_Iic_eq_lintegral_Iio_add_Icc {y z : ℝ} (f : ℝ → ℝ≥0∞) (hzy : z ≤ y) :
    ∫⁻ x in Iic y, f x = (∫⁻ x in Iio z, f x) + ∫⁻ x in Icc z y, f x := by
  rw [← Iio_union_Icc_eq_Iic hzy, lintegral_union measurableSet_Icc]
  rw [Set.disjoint_iff]
  

Proof state:
y z : ℝ
f : ℝ → ℝ≥0∞
hzy : z ≤ y
⊢ Iio z ∩ Icc z y ⊆ ∅

Next tactic:
rintro x ⟨h1 : x < _, h2, _⟩