l3lab/ntp-mathlib huggingface dataset:
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    apply Faithful.map_injective (F := forget CompHaus)
    

Proof state:
case h.a
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
⊢ (forget CompHaus).map (ContinuousMap.mk h ≫ g) = (forget CompHaus).map f

Next tactic:
simp only [Functor.map_comp, ContinuousMap.coe_mk, coe_comp]
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    apply Faithful.map_injective (F := forget CompHaus)
    simp only [Functor.map_comp, ContinuousMap.coe_mk, coe_comp]
    

Proof state:
case h.a
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
⊢ (forget CompHaus).map (ContinuousMap.mk (Ultrafilter.extend (g' ∘ ⇑f ∘ pure))) ≫ (forget CompHaus).map g =
    (forget CompHaus).map f

Next tactic:
convert denseRange_pure.equalizer (g.continuous.comp hh) f.continuous _
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    apply Faithful.map_injective (F := forget CompHaus)
    simp only [Functor.map_comp, ContinuousMap.coe_mk, coe_comp]
    convert denseRange_pure.equalizer (g.continuous.comp hh) f.continuous _
    -- Porting note: We need to get the coercions to functions under control.
    -- The next two lines should not be needed.
    

Proof state:
case h.a
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
⊢ (⇑g ∘ h) ∘ pure = ⇑f ∘ pure

Next tactic:
let g'' : ContinuousMap Y Z := g
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    apply Faithful.map_injective (F := forget CompHaus)
    simp only [Functor.map_comp, ContinuousMap.coe_mk, coe_comp]
    convert denseRange_pure.equalizer (g.continuous.comp hh) f.continuous _
    -- Porting note: We need to get the coercions to functions under control.
    -- The next two lines should not be needed.
    let g'' : ContinuousMap Y Z := g
    

Proof state:
case h.a
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
g'' : C(↑Y.toTop, ↑Z.toTop) := g
⊢ (⇑g ∘ h) ∘ pure = ⇑f ∘ pure

Next tactic:
have : g'' ∘ g' = id := hg'.comp_eq_id
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    apply Faithful.map_injective (F := forget CompHaus)
    simp only [Functor.map_comp, ContinuousMap.coe_mk, coe_comp]
    convert denseRange_pure.equalizer (g.continuous.comp hh) f.continuous _
    -- Porting note: We need to get the coercions to functions under control.
    -- The next two lines should not be needed.
    let g'' : ContinuousMap Y Z := g
    have : g'' ∘ g' = id := hg'.comp_eq_id
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    

Proof state:
case h.a
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
g'' : C(↑Y.toTop, ↑Z.toTop) := g
this : ⇑g'' ∘ g' = id
⊢ (⇑g ∘ h) ∘ pure = ⇑f ∘ pure

Next tactic:
erw [comp.assoc, ultrafilter_extend_extends, ← comp.assoc, this, comp.left_id]
/-- Composing two multiplications on the left by `y` then `x`
is equal to a multiplication on the left by `x * y`.
-/
@[to_additive (attr := simp) "Composing two additions on the left by `y` then `x`
is equal to an addition on the left by `x + y`."]
theorem comp_mul_left [Semigroup α] (x y : α) : (x * ·) ∘ (y * ·) = (x * y * ·) := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Semigroup α
x y : α
⊢ ((fun x_1 => x * x_1) ∘ fun x => y * x) = fun x_1 => x * y * x_1

Next tactic:
ext z
/-- Composing two multiplications on the left by `y` then `x`
is equal to a multiplication on the left by `x * y`.
-/
@[to_additive (attr := simp) "Composing two additions on the left by `y` then `x`
is equal to an addition on the left by `x + y`."]
theorem comp_mul_left [Semigroup α] (x y : α) : (x * ·) ∘ (y * ·) = (x * y * ·) := by
  ext z
  

Proof state:
case h
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Semigroup α
x y z : α
⊢ ((fun x_1 => x * x_1) ∘ fun x => y * x) z = x * y * z

Next tactic:
simp [mul_assoc]
/-- Composing two multiplications on the right by `y` and `x`
is equal to a multiplication on the right by `y * x`.
-/
@[to_additive (attr := simp) "Composing two additions on the right by `y` and `x`
is equal to an addition on the right by `y + x`."]
theorem comp_mul_right [Semigroup α] (x y : α) : (· * x) ∘ (· * y) = (· * (y * x)) := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Semigroup α
x y : α
⊢ ((fun x_1 => x_1 * x) ∘ fun x => x * y) = fun x_1 => x_1 * (y * x)

Next tactic:
ext z
/-- Composing two multiplications on the right by `y` and `x`
is equal to a multiplication on the right by `y * x`.
-/
@[to_additive (attr := simp) "Composing two additions on the right by `y` and `x`
is equal to an addition on the right by `y + x`."]
theorem comp_mul_right [Semigroup α] (x y : α) : (· * x) ∘ (· * y) = (· * (y * x)) := by
  ext z
  

Proof state:
case h
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Semigroup α
x y z : α
⊢ ((fun x_1 => x_1 * x) ∘ fun x => x * y) z = z * (y * x)

Next tactic:
simp [mul_assoc]
@[to_additive]
theorem ite_mul_one {P : Prop} [Decidable P] {a b : M} :
    ite P (a * b) 1 = ite P a 1 * ite P b 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
⊢ (if P then a * b else 1) = (if P then a else 1) * if P then b else 1

Next tactic:
by_cases h:P
@[to_additive]
theorem ite_mul_one {P : Prop} [Decidable P] {a b : M} :
    ite P (a * b) 1 = ite P a 1 * ite P b 1 := by
  by_cases h:P <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
h : P
⊢ (if P then a * b else 1) = (if P then a else 1) * if P then b else 1

Next tactic:
simp [h]
@[to_additive]
theorem ite_mul_one {P : Prop} [Decidable P] {a b : M} :
    ite P (a * b) 1 = ite P a 1 * ite P b 1 := by
  by_cases h:P <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
h : ¬P
⊢ (if P then a * b else 1) = (if P then a else 1) * if P then b else 1

Next tactic:
simp [h]
@[to_additive]
theorem ite_one_mul {P : Prop} [Decidable P] {a b : M} :
    ite P 1 (a * b) = ite P 1 a * ite P 1 b := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
⊢ (if P then 1 else a * b) = (if P then 1 else a) * if P then 1 else b

Next tactic:
by_cases h:P
@[to_additive]
theorem ite_one_mul {P : Prop} [Decidable P] {a b : M} :
    ite P 1 (a * b) = ite P 1 a * ite P 1 b := by
  by_cases h:P <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
h : P
⊢ (if P then 1 else a * b) = (if P then 1 else a) * if P then 1 else b

Next tactic:
simp [h]
@[to_additive]
theorem ite_one_mul {P : Prop} [Decidable P] {a b : M} :
    ite P 1 (a * b) = ite P 1 a * ite P 1 b := by
  by_cases h:P <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : MulOneClass M
P : Prop
inst✝ : Decidable P
a b : M
h : ¬P
⊢ (if P then 1 else a * b) = (if P then 1 else a) * if P then 1 else b

Next tactic:
simp [h]
@[to_additive]
theorem eq_one_iff_eq_one_of_mul_eq_one {a b : M} (h : a * b = 1) : a = 1 ↔ b = 1 := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : MulOneClass M
a b : M
h : a * b = 1
⊢ a = 1 ↔ b = 1

Next tactic:
constructor
@[to_additive]
theorem eq_one_iff_eq_one_of_mul_eq_one {a b : M} (h : a * b = 1) : a = 1 ↔ b = 1 := by
  constructor <;> (

Proof state:
case mp
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : MulOneClass M
a b : M
h : a * b = 1
⊢ a = 1 → b = 1

Next tactic:
rintro rfl
@[to_additive]
theorem eq_one_iff_eq_one_of_mul_eq_one {a b : M} (h : a * b = 1) : a = 1 ↔ b = 1 := by
  constructor <;> (rintro rfl; 

Proof state:
case mp
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : MulOneClass M
b : M
h : 1 * b = 1
⊢ b = 1

Next tactic:
simpa using h
@[to_additive]
theorem eq_one_iff_eq_one_of_mul_eq_one {a b : M} (h : a * b = 1) : a = 1 ↔ b = 1 := by
  constructor <;> (

Proof state:
case mpr
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : MulOneClass M
a b : M
h : a * b = 1
⊢ b = 1 → a = 1

Next tactic:
rintro rfl
@[to_additive]
theorem eq_one_iff_eq_one_of_mul_eq_one {a b : M} (h : a * b = 1) : a = 1 ↔ b = 1 := by
  constructor <;> (rintro rfl; 

Proof state:
case mpr
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : MulOneClass M
a : M
h : a * 1 = 1
⊢ a = 1

Next tactic:
simpa using h
@[to_additive]
theorem mul_mul_mul_comm (a b c d : G) : a * b * (c * d) = a * c * (b * d) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : CommSemigroup G
a b c d : G
⊢ a * b * (c * d) = a * c * (b * d)

Next tactic:
simp only [mul_left_comm, mul_assoc]
@[to_additive]
theorem mul_rotate (a b c : G) : a * b * c = b * c * a :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : CommSemigroup G
a b c : G
⊢ a * b * c = b * c * a

Next tactic:
simp only [mul_left_comm, mul_comm]
@[to_additive]
theorem mul_rotate' (a b c : G) : a * (b * c) = b * (c * a) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : CommSemigroup G
a b c : G
⊢ a * (b * c) = b * (c * a)

Next tactic:
simp only [mul_left_comm, mul_comm]
theorem bit1_add' [One M] (a b : M) : bit1 (a + b) = bit1 a + bit0 b := by
  

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : AddCommSemigroup M
inst✝ : One M
a b : M
⊢ bit1 (a + b) = bit1 a + bit0 b

Next tactic:
rw [add_comm, bit1_add, add_comm]
@[simp]
theorem bit1_zero [One M] : bit1 (0 : M) = 1 := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝¹ : AddMonoid M
a b c : M
inst✝ : One M
⊢ bit1 0 = 1

Next tactic:
rw [bit1, bit0_zero, zero_add]
@[to_additive (attr := simp)]
theorem mul_right_eq_self : a * b = a ↔ b = 1 := calc
  a * b = a ↔ a * b = a * 1 := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : LeftCancelMonoid M
a b : M
⊢ a * b = a ↔ a * b = a * 1

Next tactic:
rw [mul_one]
@[to_additive (attr := simp)]
theorem mul_left_eq_self : a * b = b ↔ a = 1 := calc
  a * b = b ↔ a * b = 1 * b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
M : Type u
inst✝ : RightCancelMonoid M
a b : M
⊢ a * b = b ↔ a * b = 1 * b

Next tactic:
rw [one_mul]
@[to_additive, field_simps] -- The attributes are out of order on purpose
theorem inv_eq_one_div (x : G) : x⁻¹ = 1 / x := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvMonoid G
a b c x : G
⊢ x⁻¹ = 1 / x

Next tactic:
rw [div_eq_mul_inv, one_mul]
@[to_additive]
theorem mul_one_div (x y : G) : x * (1 / y) = x / y :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvMonoid G
a b c x y : G
⊢ x * (1 / y) = x / y

Next tactic:
rw [div_eq_mul_inv, one_mul, div_eq_mul_inv]
@[to_additive]
theorem mul_div_assoc (a b c : G) : a * b / c = a * (b / c) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvMonoid G
a✝ b✝ c✝ a b c : G
⊢ a * b / c = a * (b / c)

Next tactic:
rw [div_eq_mul_inv, div_eq_mul_inv, mul_assoc _ _ _]
@[to_additive]
theorem mul_div (a b c : G) : a * (b / c) = a * b / c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvMonoid G
a✝ b✝ c✝ a b c : G
⊢ a * (b / c) = a * b / c

Next tactic:
simp only [mul_assoc, div_eq_mul_inv]
@[to_additive]
theorem div_eq_mul_one_div (a b : G) : a / b = a * (1 / b) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvMonoid G
a✝ b✝ c a b : G
⊢ a / b = a * (1 / b)

Next tactic:
rw [div_eq_mul_inv, one_div]
@[to_additive (attr := simp)]
theorem div_one (a : G) : a / 1 = a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivInvOneMonoid G
a : G
⊢ a / 1 = a

Next tactic:
simp [div_eq_mul_inv]
@[to_additive]
theorem eq_one_div_of_mul_eq_one_left (h : b * a = 1) : b = 1 / a :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
h : b * a = 1
⊢ b = 1 / a

Next tactic:
rw [eq_inv_of_mul_eq_one_left h, one_div]
@[to_additive]
theorem eq_one_div_of_mul_eq_one_right (h : a * b = 1) : b = 1 / a :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
h : a * b = 1
⊢ b = 1 / a

Next tactic:
rw [eq_inv_of_mul_eq_one_right h, one_div]
@[to_additive]
theorem eq_of_div_eq_one (h : a / b = 1) : a = b :=
  inv_injective <| inv_eq_of_mul_eq_one_right <| by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
h : a / b = 1
⊢ a * b⁻¹ = 1

Next tactic:
rwa [← div_eq_mul_inv]
@[to_additive]
theorem one_div_mul_one_div_rev : 1 / a * (1 / b) = 1 / (b * a) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ 1 / a * (1 / b) = 1 / (b * a)

Next tactic:
simp
@[to_additive]
theorem inv_div_left : a⁻¹ / b = (b * a)⁻¹ := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ a⁻¹ / b = (b * a)⁻¹

Next tactic:
simp
@[to_additive (attr := simp)]
theorem inv_div : (a / b)⁻¹ = b / a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ (a / b)⁻¹ = b / a

Next tactic:
simp
@[to_additive]
theorem one_div_div : 1 / (a / b) = b / a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ 1 / (a / b) = b / a

Next tactic:
simp
@[to_additive]
theorem one_div_one_div : 1 / (1 / a) = a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ 1 / (1 / a) = a

Next tactic:
simp
@[to_additive SubtractionMonoid.toSubNegZeroMonoid]
instance (priority := 100) DivisionMonoid.toDivInvOneMonoid : DivInvOneMonoid α :=
  { DivisionMonoid.toDivInvMonoid with
    inv_one := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
src✝ : DivInvMonoid α := toDivInvMonoid
⊢ 1⁻¹ = 1

Next tactic:
simpa only [one_div, inv_inv] using (inv_div (1 : α) 1).symm
@[to_additive]
theorem eq_of_one_div_eq_one_div (h : 1 / a = 1 / b) : a = b :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
h : 1 / a = 1 / b
⊢ a = b

Next tactic:
rw [← one_div_one_div a, h, one_div_one_div]
@[to_additive, field_simps] -- The attributes are out of order on purpose
theorem div_div_eq_mul_div : a / (b / c) = a * c / b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ a / (b / c) = a * c / b

Next tactic:
simp
@[to_additive (attr := simp)]
theorem div_inv_eq_mul : a / b⁻¹ = a * b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ a / b⁻¹ = a * b

Next tactic:
simp
@[to_additive]
theorem div_mul_eq_div_div_swap : a / (b * c) = a / c / b :=
  by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionMonoid α
a b c : α
⊢ a / (b * c) = a / c / b

Next tactic:
simp only [mul_assoc, mul_inv_rev, div_eq_mul_inv]
@[to_additive neg_add]
theorem mul_inv : (a * b)⁻¹ = a⁻¹ * b⁻¹ := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ (a * b)⁻¹ = a⁻¹ * b⁻¹

Next tactic:
simp
@[to_additive]
theorem inv_div' : (a / b)⁻¹ = a⁻¹ / b⁻¹ := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ (a / b)⁻¹ = a⁻¹ / b⁻¹

Next tactic:
simp
@[to_additive]
theorem div_eq_inv_mul : a / b = b⁻¹ * a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b = b⁻¹ * a

Next tactic:
simp
@[to_additive]
theorem inv_mul_eq_div : a⁻¹ * b = b / a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a⁻¹ * b = b / a

Next tactic:
simp
@[to_additive]
theorem inv_mul' : (a * b)⁻¹ = a⁻¹ / b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ (a * b)⁻¹ = a⁻¹ / b

Next tactic:
simp
@[to_additive]
theorem inv_div_inv : a⁻¹ / b⁻¹ = b / a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a⁻¹ / b⁻¹ = b / a

Next tactic:
simp
@[to_additive]
theorem inv_inv_div_inv : (a⁻¹ / b⁻¹)⁻¹ = a / b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ (a⁻¹ / b⁻¹)⁻¹ = a / b

Next tactic:
simp
@[to_additive]
theorem one_div_mul_one_div : 1 / a * (1 / b) = 1 / (a * b) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ 1 / a * (1 / b) = 1 / (a * b)

Next tactic:
simp
@[to_additive]
theorem div_right_comm : a / b / c = a / c / b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b / c = a / c / b

Next tactic:
simp
@[to_additive, field_simps]
theorem div_div : a / b / c = a / (b * c) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b / c = a / (b * c)

Next tactic:
simp
@[to_additive]
theorem div_mul : a / b * c = a / (b / c) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b * c = a / (b / c)

Next tactic:
simp
@[to_additive]
theorem mul_div_left_comm : a * (b / c) = b * (a / c) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a * (b / c) = b * (a / c)

Next tactic:
simp
@[to_additive]
theorem mul_div_right_comm : a * b / c = a / c * b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a * b / c = a / c * b

Next tactic:
simp
@[to_additive]
theorem div_mul_eq_div_div : a / (b * c) = a / b / c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / (b * c) = a / b / c

Next tactic:
simp
@[to_additive, field_simps]
theorem div_mul_eq_mul_div : a / b * c = a * c / b := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b * c = a * c / b

Next tactic:
simp
@[to_additive]
theorem mul_comm_div : a / b * c = a * (c / b) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b * c = a * (c / b)

Next tactic:
simp
@[to_additive]
theorem div_mul_comm : a / b * c = c / b * a := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b * c = c / b * a

Next tactic:
simp
@[to_additive]
theorem div_mul_eq_div_mul_one_div : a / (b * c) = a / b * (1 / c) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / (b * c) = a / b * (1 / c)

Next tactic:
simp
@[to_additive]
theorem div_div_div_eq : a / b / (c / d) = a * d / (b * c) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b / (c / d) = a * d / (b * c)

Next tactic:
simp
@[to_additive]
theorem div_div_div_comm : a / b / (c / d) = a / c / (b / d) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b / (c / d) = a / c / (b / d)

Next tactic:
simp
@[to_additive]
theorem div_mul_div_comm : a / b * (c / d) = a * c / (b * d) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a / b * (c / d) = a * c / (b * d)

Next tactic:
simp
@[to_additive]
theorem mul_div_mul_comm : a * b / (c * d) = a / c * (b / d) := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : DivisionCommMonoid α
a b c d : α
⊢ a * b / (c * d) = a / c * (b / d)

Next tactic:
simp
@[to_additive (attr := simp)]
theorem div_eq_inv_self : a / b = b⁻¹ ↔ a = 1 := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
⊢ a / b = b⁻¹ ↔ a = 1

Next tactic:
rw [div_eq_mul_inv, mul_left_eq_self]
@[to_additive]
theorem eq_mul_inv_of_mul_eq (h : a * c = b) : a = b * c⁻¹ := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : a * c = b
⊢ a = b * c⁻¹

Next tactic:
simp [h.symm]
@[to_additive]
theorem eq_inv_mul_of_mul_eq (h : b * a = c) : a = b⁻¹ * c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : b * a = c
⊢ a = b⁻¹ * c

Next tactic:
simp [h.symm]
@[to_additive]
theorem inv_mul_eq_of_eq_mul (h : b = a * c) : a⁻¹ * b = c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : b = a * c
⊢ a⁻¹ * b = c

Next tactic:
simp [h]
@[to_additive]
theorem mul_inv_eq_of_eq_mul (h : a = c * b) : a * b⁻¹ = c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : a = c * b
⊢ a * b⁻¹ = c

Next tactic:
simp [h]
@[to_additive]
theorem eq_mul_of_mul_inv_eq (h : a * c⁻¹ = b) : a = b * c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : a * c⁻¹ = b
⊢ a = b * c

Next tactic:
simp [h.symm]
@[to_additive]
theorem eq_mul_of_inv_mul_eq (h : b⁻¹ * a = c) : a = b * c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : b⁻¹ * a = c
⊢ a = b * c

Next tactic:
simp [h.symm, mul_inv_cancel_left]
@[to_additive]
theorem mul_eq_of_eq_inv_mul (h : b = a⁻¹ * c) : a * b = c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : b = a⁻¹ * c
⊢ a * b = c

Next tactic:
rw [h, mul_inv_cancel_left]
@[to_additive]
theorem mul_eq_of_eq_mul_inv (h : a = c * b⁻¹) : a * b = c := by 

Proof state:
α : Type u_1
β : Type u_2
G : Type u_3
inst✝ : Group G
a b c d : G
h : a = c * b⁻¹
⊢ a * b = c

Next tactic:
simp [h]