l3lab/ntp-mathlib huggingface dataset:
@[to_additive] private def Prod.upMulHom : G × H →ₙ* ∀ b, I G H b :=
  ⟨fun x ↦ Bool.rec ⟨x.1⟩ ⟨x.2⟩, fun x y ↦ by ext (_|_) <;> 

Proof state:
case h.true.h
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
x y : G × H
⊢ ((fun x t => Bool.rec { down := x.1 } { down := x.2 } t) (x * y) true).down =
    (((fun x t => Bool.rec { down := x.1 } { down := x.2 } t) x *
          (fun x t => Bool.rec { down := x.1 } { down := x.2 } t) y)
        true).down

Next tactic:
rfl
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
    UniqueProds H where
  uniqueMul_of_nonempty {A B} A0 B0 := by
    

Proof state:
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
f : H →ₙ* G
hf : Function.Injective ⇑f
uG : UniqueProds G
A B : Finset H
A0 : Finset.Nonempty A
B0 : Finset.Nonempty B
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
classical
    obtain ⟨a0, ha0, b0, hb0, h⟩ := uG.uniqueMul_of_nonempty (A0.image f) (B0.image f)
    rcases mem_image.mp ha0 with ⟨a', ha', rfl⟩
    rcases mem_image.mp hb0 with ⟨b', hb', rfl⟩
    exact ⟨a', ha', b', hb', (UniqueMul.mulHom_image_iff f hf).mp h⟩
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
    UniqueProds H where
  uniqueMul_of_nonempty {A B} A0 B0 := by
    classical
    

Proof state:
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
f : H →ₙ* G
hf : Function.Injective ⇑f
uG : UniqueProds G
A B : Finset H
A0 : Finset.Nonempty A
B0 : Finset.Nonempty B
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
obtain ⟨a0, ha0, b0, hb0, h⟩ := uG.uniqueMul_of_nonempty (A0.image f) (B0.image f)
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
    UniqueProds H where
  uniqueMul_of_nonempty {A B} A0 B0 := by
    classical
    obtain ⟨a0, ha0, b0, hb0, h⟩ := uG.uniqueMul_of_nonempty (A0.image f) (B0.image f)
    

Proof state:
case intro.intro.intro.intro
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
f : H →ₙ* G
hf : Function.Injective ⇑f
uG : UniqueProds G
A B : Finset H
A0 : Finset.Nonempty A
B0 : Finset.Nonempty B
a0 : G
ha0 : a0 ∈ image (⇑f) A
b0 : G
hb0 : b0 ∈ image (⇑f) B
h : UniqueMul (image (⇑f) A) (image (⇑f) B) a0 b0
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
rcases mem_image.mp ha0 with ⟨a', ha', rfl⟩
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
    UniqueProds H where
  uniqueMul_of_nonempty {A B} A0 B0 := by
    classical
    obtain ⟨a0, ha0, b0, hb0, h⟩ := uG.uniqueMul_of_nonempty (A0.image f) (B0.image f)
    rcases mem_image.mp ha0 with ⟨a', ha', rfl⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
f : H →ₙ* G
hf : Function.Injective ⇑f
uG : UniqueProds G
A B : Finset H
A0 : Finset.Nonempty A
B0 : Finset.Nonempty B
b0 : G
hb0 : b0 ∈ image (⇑f) B
a' : H
ha' : a' ∈ A
ha0 : f a' ∈ image (⇑f) A
h : UniqueMul (image (⇑f) A) (image (⇑f) B) (f a') b0
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
rcases mem_image.mp hb0 with ⟨b', hb', rfl⟩
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
    UniqueProds H where
  uniqueMul_of_nonempty {A B} A0 B0 := by
    classical
    obtain ⟨a0, ha0, b0, hb0, h⟩ := uG.uniqueMul_of_nonempty (A0.image f) (B0.image f)
    rcases mem_image.mp ha0 with ⟨a', ha', rfl⟩
    rcases mem_image.mp hb0 with ⟨b', hb', rfl⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
G : Type u
H : Type v
inst✝¹ : Mul G
inst✝ : Mul H
f : H →ₙ* G
hf : Function.Injective ⇑f
uG : UniqueProds G
A B : Finset H
A0 : Finset.Nonempty A
B0 : Finset.Nonempty B
a' : H
ha' : a' ∈ A
ha0 : f a' ∈ image (⇑f) A
b' : H
hb' : b' ∈ B
hb0 : f b' ∈ image (⇑f) B
h : UniqueMul (image (⇑f) A) (image (⇑f) B) (f a') (f b')
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
exact ⟨a', ha', b', hb', (UniqueMul.mulHom_image_iff f hf).mp h⟩
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    

Proof state:
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b2 : G
he : a * b1 = a * b2
⊢ b1 = b2

Next tactic:
classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    cases mem_singleton.mp ha
    simp_rw [mem_insert, mem_singleton] at hb
    obtain rfl | rfl := hb
    · exact (hu ha (mem_insert_of_mem <| mem_singleton_self b2) he.symm).2.symm
    · exact (hu ha this he).2
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    

Proof state:
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b2 : G
he : a * b1 = a * b2
⊢ b1 = b2

Next tactic:
have := mem_insert_self b1 {b2}
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    

Proof state:
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b2 : G
he : a * b1 = a * b2
this : b1 ∈ {b1, b2}
⊢ b1 = b2

Next tactic:
obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    

Proof state:
case intro.intro.intro.intro
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a✝ b1 b2 : G
he : a✝ * b1 = a✝ * b2
this : b1 ∈ {b1, b2}
a : G
ha : a ∈ {a✝}
b : G
hb : b ∈ {b1, b2}
hu : UniqueMul {a✝} {b1, b2} a b
⊢ b1 = b2

Next tactic:
cases mem_singleton.mp ha
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    cases mem_singleton.mp ha
    

Proof state:
case intro.intro.intro.intro.refl
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b2 : G
he : a * b1 = a * b2
this : b1 ∈ {b1, b2}
b : G
hb : b ∈ {b1, b2}
ha : a ∈ {a}
hu : UniqueMul {a} {b1, b2} a b
⊢ b1 = b2

Next tactic:
simp_rw [mem_insert, mem_singleton] at hb
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    cases mem_singleton.mp ha
    simp_rw [mem_insert, mem_singleton] at hb
    

Proof state:
case intro.intro.intro.intro.refl
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b2 : G
he : a * b1 = a * b2
this : b1 ∈ {b1, b2}
b : G
ha : a ∈ {a}
hu : UniqueMul {a} {b1, b2} a b
hb : b = b1 ∨ b = b2
⊢ b1 = b2

Next tactic:
obtain rfl | rfl := hb
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    cases mem_singleton.mp ha
    simp_rw [mem_insert, mem_singleton] at hb
    obtain rfl | rfl := hb
    · 

Proof state:
case intro.intro.intro.intro.refl.inl
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b2 b : G
ha : a ∈ {a}
he : a * b = a * b2
this : b ∈ {b, b2}
hu : UniqueMul {a} {b, b2} a b
⊢ b = b2

Next tactic:
exact (hu ha (mem_insert_of_mem <| mem_singleton_self b2) he.symm).2.symm
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
  mul_left_cancel a b1 b2 he := by
    classical
    have := mem_insert_self b1 {b2}
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty ⟨a, mem_singleton_self a⟩ ⟨b1, this⟩
    cases mem_singleton.mp ha
    simp_rw [mem_insert, mem_singleton] at hb
    obtain rfl | rfl := hb
    · exact (hu ha (mem_insert_of_mem <| mem_singleton_self b2) he.symm).2.symm
    · 

Proof state:
case intro.intro.intro.intro.refl.inr
G : Type u
H : Type v
inst✝² : Mul G
inst✝¹ : Mul H
inst✝ : UniqueProds G
a b1 b : G
ha : a ∈ {a}
he : a * b1 = a * b
this : b1 ∈ {b1, b}
hu : UniqueMul {a} {b1, b} a b
⊢ b1 = b

Next tactic:
exact (hu ha this he).2
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    

Proof state:
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
    refine ⟨a1, ha1, b2, hb2, fun a b ha hb he => ?_⟩
    specialize hu (mul_mem_mul hb1 ha) (mul_mem_mul hb ha2) _
    · rw [mul_assoc b1, ← mul_assoc a, he, mul_assoc a1, ← mul_assoc b1]
    exact ⟨mul_left_cancel hu.1, mul_right_cancel hu.2⟩
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    

Proof state:
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    

Proof state:
case intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
g1 : G
h1 : g1 ∈ B * A
g2 : G
h2 : g2 ∈ B * A
hu : UniqueMul (B * A) (B * A) g1 g2
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
g2 : G
h2 : g2 ∈ B * A
b1 a1 : G
hb1 : b1 ∈ B
ha1 : a1 ∈ A
h1 : b1 * a1 ∈ B * A
hu : UniqueMul (B * A) (B * A) (b1 * a1) g2
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
b1 a1 : G
hb1 : b1 ∈ B
ha1 : a1 ∈ A
h1 : b1 * a1 ∈ B * A
b2 a2 : G
hb2 : b2 ∈ B
ha2 : a2 ∈ A
h2 : b2 * a2 ∈ B * A
hu : UniqueMul (B * A) (B * A) (b1 * a1) (b2 * a2)
⊢ ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

Next tactic:
refine ⟨a1, ha1, b2, hb2, fun a b ha hb he => ?_⟩
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
    refine ⟨a1, ha1, b2, hb2, fun a b ha hb he => ?_⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
b1 a1 : G
hb1 : b1 ∈ B
ha1 : a1 ∈ A
h1 : b1 * a1 ∈ B * A
b2 a2 : G
hb2 : b2 ∈ B
ha2 : a2 ∈ A
h2 : b2 * a2 ∈ B * A
hu : UniqueMul (B * A) (B * A) (b1 * a1) (b2 * a2)
a b : G
ha : a ∈ A
hb : b ∈ B
he : a * b = a1 * b2
⊢ a = a1 ∧ b = b2

Next tactic:
specialize hu (mul_mem_mul hb1 ha) (mul_mem_mul hb ha2) _
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
    refine ⟨a1, ha1, b2, hb2, fun a b ha hb he => ?_⟩
    specialize hu (mul_mem_mul hb1 ha) (mul_mem_mul hb ha2) _
    · 

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
b1 a1 : G
hb1 : b1 ∈ B
ha1 : a1 ∈ A
h1 : b1 * a1 ∈ B * A
b2 a2 : G
hb2 : b2 ∈ B
ha2 : a2 ∈ A
h2 : b2 * a2 ∈ B * A
hu : UniqueMul (B * A) (B * A) (b1 * a1) (b2 * a2)
a b : G
ha : a ∈ A
hb : b ∈ B
he : a * b = a1 * b2
⊢ b1 * a * (b * a2) = b1 * a1 * (b2 * a2)

Next tactic:
rw [mul_assoc b1, ← mul_assoc a, he, mul_assoc a1, ← mul_assoc b1]
/-- `UniqueProds G` says that for any two nonempty `Finset`s `A` and `B` in `G`, `A × B`
  contains a unique pair with the `UniqueMul` property. Strojnowski showed that if `G` is
  a group, then we only need to check this when `A = B`.
  Here we generalize the result to cancellative semigroups.
  Non-cancellative counterexample: the AddMonoid {0,1} with 1+1=1. -/
@[to_additive] theorem of_same {G} [Semigroup G] [IsCancelMul G]
    (h : ∀ {A : Finset G}, A.Nonempty → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2) :
    UniqueProds G where
  uniqueMul_of_nonempty {A B} hA hB := by
    classical
    obtain ⟨g1, h1, g2, h2, hu⟩ := h (hB.mul hA)
    obtain ⟨b1, a1, hb1, ha1, rfl⟩ := mem_mul.mp h1
    obtain ⟨b2, a2, hb2, ha2, rfl⟩ := mem_mul.mp h2
    refine ⟨a1, ha1, b2, hb2, fun a b ha hb he => ?_⟩
    specialize hu (mul_mem_mul hb1 ha) (mul_mem_mul hb ha2) _
    · rw [mul_assoc b1, ← mul_assoc a, he, mul_assoc a1, ← mul_assoc b1]
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Semigroup G
inst✝ : IsCancelMul G
h : ∀ {A : Finset G}, Finset.Nonempty A → ∃ a1 ∈ A, ∃ a2 ∈ A, UniqueMul A A a1 a2
A B : Finset G
hA : Finset.Nonempty A
hB : Finset.Nonempty B
b1 a1 : G
hb1 : b1 ∈ B
ha1 : a1 ∈ A
h1 : b1 * a1 ∈ B * A
b2 a2 : G
hb2 : b2 ∈ B
ha2 : a2 ∈ A
h2 : b2 * a2 ∈ B * A
a b : G
ha : a ∈ A
hb : b ∈ B
he : a * b = a1 * b2
hu : b1 * a = b1 * a1 ∧ b * a2 = b2 * a2
⊢ a = a1 ∧ b = b2

Next tactic:
exact ⟨mul_left_cancel hu.1, mul_right_cancel hu.2⟩
/-- If a group has `UniqueProds`, then it actually has `TwoUniqueProds`.
  For an example of a semigroup `G` embeddable into a group that has `UniqueProds`
  but not `TwoUniqueProds`, see Example 10.13 in
  [J. Okniński, *Semigroup Algebras*][Okninski1991]. -/
@[to_additive] theorem toTwoUniqueProds_of_group {G}
    [Group G] [UniqueProds G] : TwoUniqueProds G where
  uniqueMul_of_one_lt_card {A B} hc := by
    

Proof state:
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Group G
inst✝ : UniqueProds G
A B : Finset G
hc : 1 < card A * card B
⊢ ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

Next tactic:
simp_rw [Nat.one_lt_mul_iff, card_pos] at hc
/-- If a group has `UniqueProds`, then it actually has `TwoUniqueProds`.
  For an example of a semigroup `G` embeddable into a group that has `UniqueProds`
  but not `TwoUniqueProds`, see Example 10.13 in
  [J. Okniński, *Semigroup Algebras*][Okninski1991]. -/
@[to_additive] theorem toTwoUniqueProds_of_group {G}
    [Group G] [UniqueProds G] : TwoUniqueProds G where
  uniqueMul_of_one_lt_card {A B} hc := by
    simp_rw [Nat.one_lt_mul_iff, card_pos] at hc
    

Proof state:
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Group G
inst✝ : UniqueProds G
A B : Finset G
hc : Finset.Nonempty A ∧ Finset.Nonempty B ∧ (1 < card A ∨ 1 < card B)
⊢ ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

Next tactic:
obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty hc.1 hc.2.1
/-- If a group has `UniqueProds`, then it actually has `TwoUniqueProds`.
  For an example of a semigroup `G` embeddable into a group that has `UniqueProds`
  but not `TwoUniqueProds`, see Example 10.13 in
  [J. Okniński, *Semigroup Algebras*][Okninski1991]. -/
@[to_additive] theorem toTwoUniqueProds_of_group {G}
    [Group G] [UniqueProds G] : TwoUniqueProds G where
  uniqueMul_of_one_lt_card {A B} hc := by
    simp_rw [Nat.one_lt_mul_iff, card_pos] at hc
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty hc.1 hc.2.1
    

Proof state:
case intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Group G
inst✝ : UniqueProds G
A B : Finset G
hc : Finset.Nonempty A ∧ Finset.Nonempty B ∧ (1 < card A ∨ 1 < card B)
a : G
ha : a ∈ A
b : G
hb : b ∈ B
hu : UniqueMul A B a b
⊢ ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

Next tactic:
let C := A.map ⟨_, mul_right_injective a⁻¹⟩
/-- If a group has `UniqueProds`, then it actually has `TwoUniqueProds`.
  For an example of a semigroup `G` embeddable into a group that has `UniqueProds`
  but not `TwoUniqueProds`, see Example 10.13 in
  [J. Okniński, *Semigroup Algebras*][Okninski1991]. -/
@[to_additive] theorem toTwoUniqueProds_of_group {G}
    [Group G] [UniqueProds G] : TwoUniqueProds G where
  uniqueMul_of_one_lt_card {A B} hc := by
    simp_rw [Nat.one_lt_mul_iff, card_pos] at hc
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty hc.1 hc.2.1
    let C := A.map ⟨_, mul_right_injective a⁻¹⟩ -- C = a⁻¹A
    

Proof state:
case intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Group G
inst✝ : UniqueProds G
A B : Finset G
hc : Finset.Nonempty A ∧ Finset.Nonempty B ∧ (1 < card A ∨ 1 < card B)
a : G
ha : a ∈ A
b : G
hb : b ∈ B
hu : UniqueMul A B a b
C : Finset G := map { toFun := fun x => a⁻¹ * x, inj' := (_ : Function.Injective fun x => a⁻¹ * x) } A
⊢ ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

Next tactic:
let D := B.map ⟨_, mul_left_injective b⁻¹⟩
/-- If a group has `UniqueProds`, then it actually has `TwoUniqueProds`.
  For an example of a semigroup `G` embeddable into a group that has `UniqueProds`
  but not `TwoUniqueProds`, see Example 10.13 in
  [J. Okniński, *Semigroup Algebras*][Okninski1991]. -/
@[to_additive] theorem toTwoUniqueProds_of_group {G}
    [Group G] [UniqueProds G] : TwoUniqueProds G where
  uniqueMul_of_one_lt_card {A B} hc := by
    simp_rw [Nat.one_lt_mul_iff, card_pos] at hc
    obtain ⟨a, ha, b, hb, hu⟩ := uniqueMul_of_nonempty hc.1 hc.2.1
    let C := A.map ⟨_, mul_right_injective a⁻¹⟩ -- C = a⁻¹A
    let D := B.map ⟨_, mul_left_injective b⁻¹⟩  -- D = Bb⁻¹
    

Proof state:
case intro.intro.intro.intro
G✝ : Type u
H : Type v
inst✝³ : Mul G✝
inst✝² : Mul H
G : Type u_1
inst✝¹ : Group G
inst✝ : UniqueProds G
A B : Finset G
hc : Finset.Nonempty A ∧ Finset.Nonempty B ∧ (1 < card A ∨ 1 < card B)
a : G
ha : a ∈ A
b : G
hb : b ∈ B
hu : UniqueMul A B a b
C : Finset G := map { toFun := fun x => a⁻¹ * x, inj' := (_ : Function.Injective fun x => a⁻¹ * x) } A
D : Finset G := map { toFun := fun x => x * b⁻¹, inj' := (_ : Function.Injective fun x => x * b⁻¹) } B
⊢ ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

Next tactic:
have hcard : 1 < C.card ∨ 1 < D.card