l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem mul_eq_mul_right_iff : a * c = b * c ↔ a = b ∨ c = 0 := by
  by_cases hc : c = 0 <;> [

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
hc : c = 0
⊢ a * c = b * c ↔ a = b ∨ c = 0

Next tactic:
simp [hc]
@[simp]
theorem mul_eq_mul_right_iff : a * c = b * c ↔ a = b ∨ c = 0 := by
  by_cases hc : c = 0 <;> [simp [hc]; 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
hc : ¬c = 0
⊢ a * c = b * c ↔ a = b ∨ c = 0

Next tactic:
simp [mul_left_inj', hc]
@[simp]
theorem mul_eq_mul_left_iff : a * b = a * c ↔ b = c ∨ a = 0 := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
⊢ a * b = a * c ↔ b = c ∨ a = 0

Next tactic:
by_cases ha : a = 0 <;> [simp [ha]; simp [mul_right_inj', ha]]
@[simp]
theorem mul_eq_mul_left_iff : a * b = a * c ↔ b = c ∨ a = 0 := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
⊢ a * b = a * c ↔ b = c ∨ a = 0

Next tactic:
by_cases ha : a = 0
@[simp]
theorem mul_eq_mul_left_iff : a * b = a * c ↔ b = c ∨ a = 0 := by
  by_cases ha : a = 0 <;> [

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
ha : a = 0
⊢ a * b = a * c ↔ b = c ∨ a = 0

Next tactic:
simp [ha]
@[simp]
theorem mul_eq_mul_left_iff : a * b = a * c ↔ b = c ∨ a = 0 := by
  by_cases ha : a = 0 <;> [simp [ha]; 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
ha : ¬a = 0
⊢ a * b = a * c ↔ b = c ∨ a = 0

Next tactic:
simp [mul_right_inj', ha]
theorem mul_right_eq_self₀ : a * b = a ↔ b = 1 ∨ a = 0 :=
  calc
    a * b = a ↔ a * b = a * 1 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
⊢ a * b = a ↔ a * b = a * 1

Next tactic:
rw [mul_one]
theorem mul_left_eq_self₀ : a * b = b ↔ a = 1 ∨ b = 0 :=
  calc
    a * b = b ↔ a * b = 1 * b := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
⊢ a * b = b ↔ a * b = 1 * b

Next tactic:
rw [one_mul]
@[simp]
theorem mul_eq_left₀ (ha : a ≠ 0) : a * b = a ↔ b = 1 := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
ha : a ≠ 0
⊢ a * b = a ↔ b = 1

Next tactic:
rw [Iff.comm, ← mul_right_inj' ha, mul_one]
@[simp]
theorem mul_eq_right₀ (hb : b ≠ 0) : a * b = b ↔ a = 1 := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
hb : b ≠ 0
⊢ a * b = b ↔ a = 1

Next tactic:
rw [Iff.comm, ← mul_left_inj' hb, one_mul]
@[simp]
theorem left_eq_mul₀ (ha : a ≠ 0) : a = a * b ↔ b = 1 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
ha : a ≠ 0
⊢ a = a * b ↔ b = 1

Next tactic:
rw [eq_comm, mul_eq_left₀ ha]
@[simp]
theorem right_eq_mul₀ (hb : b ≠ 0) : b = a * b ↔ a = 1 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CancelMonoidWithZero M₀
a b c : M₀
hb : b ≠ 0
⊢ b = a * b ↔ a = 1

Next tactic:
rw [eq_comm, mul_eq_right₀ hb]
theorem GroupWithZero.mul_left_injective (h : x ≠ 0) :
    Function.Injective fun y => x * y := fun y y' w => by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b c g h✝ x : G₀
h : x ≠ 0
y y' : G₀
w : (fun y => x * y) y = (fun y => x * y) y'
⊢ y = y'

Next tactic:
simpa only [← mul_assoc, inv_mul_cancel h, one_mul] using congr_arg (fun y => x⁻¹ * y) w
theorem GroupWithZero.mul_right_injective (h : x ≠ 0) :
    Function.Injective fun y => y * x := fun y y' w => by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b c g h✝ x : G₀
h : x ≠ 0
y y' : G₀
w : (fun y => y * x) y = (fun y => y * x) y'
⊢ y = y'

Next tactic:
simpa only [mul_assoc, mul_inv_cancel _ h, mul_one] using congr_arg (fun y => y * x⁻¹) w
@[simp]
theorem inv_mul_cancel_right₀ (h : b ≠ 0) (a : G₀) : a * b⁻¹ * b = a :=
  calc
    a * b⁻¹ * b = a * (b⁻¹ * b) := mul_assoc _ _ _
    _ = a := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c g h✝ x : G₀
h : b ≠ 0
a : G₀
⊢ a * (b⁻¹ * b) = a

Next tactic:
simp [h]
@[simp]
theorem inv_mul_cancel_left₀ (h : a ≠ 0) (b : G₀) : a⁻¹ * (a * b) = b :=
  calc
    a⁻¹ * (a * b) = a⁻¹ * a * b := (mul_assoc _ _ _).symm
    _ = b := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b✝ c g h✝ x : G₀
h : a ≠ 0
b : G₀
⊢ a⁻¹ * a * b = b

Next tactic:
simp [h]
private theorem inv_eq_of_mul (h : a * b = 1) : a⁻¹ = b := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b c g h✝ x : G₀
h : a * b = 1
⊢ a⁻¹ = b

Next tactic:
rw [← inv_mul_cancel_left₀ (left_ne_zero_of_mul_eq_one h) b, h, mul_one]
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a : G₀
⊢ a⁻¹⁻¹ = a

Next tactic:
by_cases h : a = 0
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c g h✝ x : G₀
src✝ : GroupWithZero G₀ := inst✝
a : G₀
h : a = 0
⊢ a⁻¹⁻¹ = a

Next tactic:
simp [h]
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c g h✝ x : G₀
src✝ : GroupWithZero G₀ := inst✝
a : G₀
h : ¬a = 0
⊢ a⁻¹⁻¹ = a

Next tactic:
exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
⊢ (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
by_cases ha : a = 0
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      by_cases ha : a = 0
      · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
ha : a = 0
⊢ (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
simp [ha]
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      by_cases ha : a = 0
      · simp [ha]

      

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
ha : ¬a = 0
⊢ (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
by_cases hb : b = 0
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      by_cases ha : a = 0
      · simp [ha]

      by_cases hb : b = 0
      · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
ha : ¬a = 0
hb : b = 0
⊢ (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
simp [hb]
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      by_cases ha : a = 0
      · simp [ha]

      by_cases hb : b = 0
      · simp [hb]

      

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
ha : ¬a = 0
hb : ¬b = 0
⊢ (a * b)⁻¹ = b⁻¹ * a⁻¹

Next tactic:
refine' inv_eq_of_mul _
instance (priority := 100) GroupWithZero.toDivisionMonoid : DivisionMonoid G₀ :=
  { ‹GroupWithZero G₀› with
    inv := Inv.inv,
    inv_inv := fun a => by
      by_cases h : a = 0
      · simp [h]

      · exact left_inv_eq_right_inv (inv_mul_cancel <| inv_ne_zero h) (inv_mul_cancel h)
        ,
    mul_inv_rev := fun a b => by
      by_cases ha : a = 0
      · simp [ha]

      by_cases hb : b = 0
      · simp [hb]

      refine' inv_eq_of_mul _
      

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b✝ c g h x : G₀
src✝ : GroupWithZero G₀ := inst✝
a b : G₀
ha : ¬a = 0
hb : ¬b = 0
⊢ a * b * (b⁻¹ * a⁻¹) = 1

Next tactic:
simp [mul_assoc, ha, hb]
instance (priority := 10) GroupWithZero.toCancelMonoidWithZero : CancelMonoidWithZero G₀ :=
  { (‹_› : GroupWithZero G₀) with
    mul_left_cancel_of_ne_zero := @fun x y z hx h => by
      

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b c g h✝ x✝ : G₀
src✝ : GroupWithZero G₀ := inst✝
x y z : G₀
hx : x ≠ 0
h : x * y = x * z
⊢ y = z

Next tactic:
rw [← inv_mul_cancel_left₀ hx y, h, inv_mul_cancel_left₀ hx z]
instance (priority := 10) GroupWithZero.toCancelMonoidWithZero : CancelMonoidWithZero G₀ :=
  { (‹_› : GroupWithZero G₀) with
    mul_left_cancel_of_ne_zero := @fun x y z hx h => by
      rw [← inv_mul_cancel_left₀ hx y, h, inv_mul_cancel_left₀ hx z],
    mul_right_cancel_of_ne_zero := @fun x y z hy h => by
      

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a b c g h✝ x✝ : G₀
src✝ : GroupWithZero G₀ := inst✝
x y z : G₀
hy : y ≠ 0
h : x * y = z * y
⊢ x = z

Next tactic:
rw [← mul_inv_cancel_right₀ hy x, h, mul_inv_cancel_right₀ hy z]
@[simp]
theorem zero_div (a : G₀) : 0 / a = 0 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ 0 / a = 0

Next tactic:
rw [div_eq_mul_inv, zero_mul]
@[simp]
theorem div_zero (a : G₀) : a / 0 = 0 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a / 0 = 0

Next tactic:
rw [div_eq_mul_inv, inv_zero, mul_zero]
/-- Multiplying `a` by itself and then by its inverse results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_self_mul_inv (a : G₀) : a * a * a⁻¹ = a := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a * a * a⁻¹ = a

Next tactic:
by_cases h : a = 0
/-- Multiplying `a` by itself and then by its inverse results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_self_mul_inv (a : G₀) : a * a * a⁻¹ = a := by
  by_cases h : a = 0
  · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a = 0
⊢ a * a * a⁻¹ = a

Next tactic:
rw [h, inv_zero, mul_zero]
/-- Multiplying `a` by itself and then by its inverse results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_self_mul_inv (a : G₀) : a * a * a⁻¹ = a := by
  by_cases h : a = 0
  · rw [h, inv_zero, mul_zero]
  · 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : ¬a = 0
⊢ a * a * a⁻¹ = a

Next tactic:
rw [mul_assoc, mul_inv_cancel h, mul_one]
/-- Multiplying `a` by its inverse and then by itself results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_inv_mul_self (a : G₀) : a * a⁻¹ * a = a := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a * a⁻¹ * a = a

Next tactic:
by_cases h : a = 0
/-- Multiplying `a` by its inverse and then by itself results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_inv_mul_self (a : G₀) : a * a⁻¹ * a = a := by
  by_cases h : a = 0
  · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a = 0
⊢ a * a⁻¹ * a = a

Next tactic:
rw [h, inv_zero, mul_zero]
/-- Multiplying `a` by its inverse and then by itself results in `a`
(whether or not `a` is zero). -/
@[simp]
theorem mul_inv_mul_self (a : G₀) : a * a⁻¹ * a = a := by
  by_cases h : a = 0
  · rw [h, inv_zero, mul_zero]
  · 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : ¬a = 0
⊢ a * a⁻¹ * a = a

Next tactic:
rw [mul_inv_cancel h, one_mul]
/-- Multiplying `a⁻¹` by `a` twice results in `a` (whether or not `a`
is zero). -/
@[simp]
theorem inv_mul_mul_self (a : G₀) : a⁻¹ * a * a = a := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a⁻¹ * a * a = a

Next tactic:
by_cases h : a = 0
/-- Multiplying `a⁻¹` by `a` twice results in `a` (whether or not `a`
is zero). -/
@[simp]
theorem inv_mul_mul_self (a : G₀) : a⁻¹ * a * a = a := by
  by_cases h : a = 0
  · 

Proof state:
case pos
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a = 0
⊢ a⁻¹ * a * a = a

Next tactic:
rw [h, inv_zero, mul_zero]
/-- Multiplying `a⁻¹` by `a` twice results in `a` (whether or not `a`
is zero). -/
@[simp]
theorem inv_mul_mul_self (a : G₀) : a⁻¹ * a * a = a := by
  by_cases h : a = 0
  · rw [h, inv_zero, mul_zero]
  · 

Proof state:
case neg
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : ¬a = 0
⊢ a⁻¹ * a * a = a

Next tactic:
rw [inv_mul_cancel h, one_mul]
/-- Multiplying `a` by itself and then dividing by itself results in `a`, whether or not `a` is
zero. -/
@[simp]
theorem mul_self_div_self (a : G₀) : a * a / a = a := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a * a / a = a

Next tactic:
rw [div_eq_mul_inv, mul_self_mul_inv a]
/-- Dividing `a` by itself and then multiplying by itself results in `a`, whether or not `a` is
zero. -/
@[simp]
theorem div_self_mul_self (a : G₀) : a / a * a = a := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a / a * a = a

Next tactic:
rw [div_eq_mul_inv, mul_inv_mul_self a]
@[simp]
theorem div_self_mul_self' (a : G₀) : a / (a * a) = a⁻¹ :=
  calc
    a / (a * a) = a⁻¹⁻¹ * a⁻¹ * a⁻¹ := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a / (a * a) = a⁻¹⁻¹ * a⁻¹ * a⁻¹

Next tactic:
simp [mul_inv_rev]
theorem one_div_ne_zero {a : G₀} (h : a ≠ 0) : 1 / a ≠ 0 := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a ≠ 0
⊢ 1 / a ≠ 0

Next tactic:
simpa only [one_div] using inv_ne_zero h
@[simp]
theorem inv_eq_zero {a : G₀} : a⁻¹ = 0 ↔ a = 0 := by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a⁻¹ = 0 ↔ a = 0

Next tactic:
rw [inv_eq_iff_eq_inv, inv_zero]
/-- Dividing `a` by the result of dividing `a` by itself results in
`a` (whether or not `a` is zero). -/
@[simp]
theorem div_div_self (a : G₀) : a / (a / a) = a := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a / (a / a) = a

Next tactic:
rw [div_div_eq_mul_div]
/-- Dividing `a` by the result of dividing `a` by itself results in
`a` (whether or not `a` is zero). -/
@[simp]
theorem div_div_self (a : G₀) : a / (a / a) = a := by
  rw [div_div_eq_mul_div]
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
⊢ a * a / a = a

Next tactic:
exact mul_self_div_self a
theorem ne_zero_of_one_div_ne_zero {a : G₀} (h : 1 / a ≠ 0) : a ≠ 0 := fun ha : a = 0 => by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : 1 / a ≠ 0
ha : a = 0
⊢ False

Next tactic:
rw [ha, div_zero] at h
theorem ne_zero_of_one_div_ne_zero {a : G₀} (h : 1 / a ≠ 0) : a ≠ 0 := fun ha : a = 0 => by
  rw [ha, div_zero] at h
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : 0 ≠ 0
ha : a = 0
⊢ False

Next tactic:
contradiction
theorem mul_left_surjective₀ {a : G₀} (h : a ≠ 0) : Surjective fun g => a * g := fun g =>
  ⟨a⁻¹ * g, by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a ≠ 0
g : G₀
⊢ (fun g => a * g) (a⁻¹ * g) = g

Next tactic:
simp [← mul_assoc, mul_inv_cancel h]
theorem mul_right_surjective₀ {a : G₀} (h : a ≠ 0) : Surjective fun g => g * a := fun g =>
  ⟨g * a⁻¹, by 

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : GroupWithZero G₀
a✝ b c a : G₀
h : a ≠ 0
g : G₀
⊢ (fun g => g * a) (g * a⁻¹) = g

Next tactic:
simp [mul_assoc, inv_mul_cancel h]
theorem div_mul_eq_mul_div₀ (a b c : G₀) : a / c * b = a * b / c := by
  

Proof state:
α : Type u_1
M₀ : Type u_2
G₀ : Type u_3
M₀' : Type u_4
G₀' : Type u_5
F : Type u_6
F' : Type u_7
inst✝ : CommGroupWithZero G₀
a✝ b✝ c✝ d a b c : G₀
⊢ a / c * b = a * b / c

Next tactic:
simp_rw [div_eq_mul_inv, mul_assoc, mul_comm c⁻¹]
@[simp]
theorem noncommFoldr_coe (l : List α) (comm) (b : β) :
    noncommFoldr f (l : Multiset α) comm b = l.foldr f b := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
l : List α
comm : Set.Pairwise {x | x ∈ ↑l} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
b : β
⊢ noncommFoldr f (↑l) comm b = List.foldr f b l

Next tactic:
simp only [noncommFoldr, coe_foldr, coe_attach, List.attach, Function.comp]
@[simp]
theorem noncommFoldr_coe (l : List α) (comm) (b : β) :
    noncommFoldr f (l : Multiset α) comm b = l.foldr f b := by
  simp only [noncommFoldr, coe_foldr, coe_attach, List.attach, Function.comp]
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
l : List α
comm : Set.Pairwise {x | x ∈ ↑l} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
b : β
⊢ List.foldr (fun x => f ↑x) b (List.pmap Subtype.mk l (_ : ∀ x ∈ l, x ∈ l)) = List.foldr f b l

Next tactic:
rw [← List.foldr_map]
@[simp]
theorem noncommFoldr_coe (l : List α) (comm) (b : β) :
    noncommFoldr f (l : Multiset α) comm b = l.foldr f b := by
  simp only [noncommFoldr, coe_foldr, coe_attach, List.attach, Function.comp]
  rw [← List.foldr_map]
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
l : List α
comm : Set.Pairwise {x | x ∈ ↑l} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
b : β
⊢ List.foldr f b (List.map (fun x => ↑x) (List.pmap Subtype.mk l (_ : ∀ x ∈ l, x ∈ l))) = List.foldr f b l

Next tactic:
simp [List.map_pmap, List.pmap_eq_map]
theorem noncommFoldr_cons (s : Multiset α) (a : α) (h h') (b : β) :
    noncommFoldr f (a ::ₘ s) h b = f a (noncommFoldr f s h' b) := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
s : Multiset α
a : α
h : Set.Pairwise {x | x ∈ a ::ₘ s} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
h' : Set.Pairwise {x | x ∈ s} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
b : β
⊢ noncommFoldr f (a ::ₘ s) h b = f a (noncommFoldr f s h' b)

Next tactic:
induction s using Quotient.inductionOn
theorem noncommFoldr_cons (s : Multiset α) (a : α) (h h') (b : β) :
    noncommFoldr f (a ::ₘ s) h b = f a (noncommFoldr f s h' b) := by
  induction s using Quotient.inductionOn
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
a : α
b : β
a✝ : List α
h : Set.Pairwise {x | x ∈ a ::ₘ ⟦a✝⟧} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
h' : Set.Pairwise {x | x ∈ ⟦a✝⟧} fun x y => ∀ (b : β), f x (f y b) = f y (f x b)
⊢ noncommFoldr f (a ::ₘ ⟦a✝⟧) h b = f a (noncommFoldr f ⟦a✝⟧ h' b)

Next tactic:
simp
theorem noncommFoldr_eq_foldr (s : Multiset α) (h : LeftCommutative f) (b : β) :
    noncommFoldr f s (fun x _ y _ _ => h x y) b = foldr f h b s := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
s : Multiset α
h : LeftCommutative f
b : β
⊢ noncommFoldr f s (_ : ∀ x ∈ {x | x ∈ s}, ∀ y ∈ {x | x ∈ s}, x ≠ y → ∀ (b : β), f x (f y b) = f y (f x b)) b =
    foldr f h b s

Next tactic:
induction s using Quotient.inductionOn