File: Mathlib/Algebra/Group/UniqueProds.lean

full_name: UniqueAdd
code: /-- Let `G` be a Type with multiplication, let `A B : Finset G` be finite subsets and
let `a0 b0 : G` be two elements.  `UniqueMul A B a0 b0` asserts `a0 * b0` can be written in at
most one way as a product of an element of `A` and an element of `B`. -/
@[to_additive
      "Let `G` be a Type with addition, let `A B : Finset G` be finite subsets and
let `a0 b0 : G` be two elements.  `UniqueAdd A B a0 b0` asserts `a0 + b0` can be written in at
most one way as a sum of an element from `A` and an element from `B`."]
def UniqueMul {G} [Mul G] (A B : Finset G) (a0 b0 : G) : Prop 
goal: Prop

full_name: UniqueMul
code: /-- Let `G` be a Type with multiplication, let `A B : Finset G` be finite subsets and
let `a0 b0 : G` be two elements.  `UniqueMul A B a0 b0` asserts `a0 * b0` can be written in at
most one way as a product of an element of `A` and an element of `B`. -/
@[to_additive
      "Let `G` be a Type with addition, let `A B : Finset G` be finite subsets and
let `a0 b0 : G` be two elements.  `UniqueAdd A B a0 b0` asserts `a0 + b0` can be written in at
most one way as a sum of an element from `A` and an element from `B`."]
def UniqueMul {G} [Mul G] (A B : Finset G) (a0 b0 : G) : Prop 
goal: Prop

full_name: UniqueMul.of_subsingleton
code: @[to_additive (attr := nontriviality, simp)]
theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 
goal: UniqueMul A B a0 b0

full_name: UniqueAdd.of_subsingleton
code: @[to_additive (attr := nontriviality, simp)]
theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 
goal: UniqueAdd A B a0 b0

full_name: UniqueMul.of_card_le_one
code: @[to_additive]
theorem of_card_le_one (hA : A.Nonempty) (hB : B.Nonempty) (hA1 : A.card ≤ 1) (hB1 : B.card ≤ 1) :
    ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b 
goal: ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b

full_name: UniqueAdd.of_card_nonpos
code: @[to_additive]
theorem of_card_le_one (hA : A.Nonempty) (hB : B.Nonempty) (hA1 : A.card ≤ 1) (hB1 : B.card ≤ 1) :
    ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b 
goal: ∃ a ∈ A, ∃ b ∈ B, UniqueAdd A B a b

full_name: UniqueMul.mt
code: @[to_additive]
theorem mt (h : UniqueMul A B a0 b0) :
    ∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 
goal: a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0

full_name: UniqueAdd.mt
code: @[to_additive]
theorem mt (h : UniqueMul A B a0 b0) :
    ∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 
goal: a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a + b ≠ a0 + b0

full_name: UniqueMul.subsingleton
code: @[to_additive]
theorem subsingleton (h : UniqueMul A B a0 b0) :
    Subsingleton { ab : G × G // ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } 
goal: Subsingleton { ab // ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 }

full_name: UniqueAdd.subsingleton
code: @[to_additive]
theorem subsingleton (h : UniqueMul A B a0 b0) :
    Subsingleton { ab : G × G // ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } 
goal: Subsingleton { ab // ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 + ab.2 = a0 + b0 }

full_name: UniqueMul.set_subsingleton
code: @[to_additive]
theorem set_subsingleton (h : UniqueMul A B a0 b0) :
    Set.Subsingleton { ab : G × G | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } 
goal: {ab | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0}.Subsingleton

full_name: UniqueAdd.set_subsingleton
code: @[to_additive]
theorem set_subsingleton (h : UniqueMul A B a0 b0) :
    Set.Subsingleton { ab : G × G | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } 
goal: {ab | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 + ab.2 = a0 + b0}.Subsingleton

full_name: UniqueAdd.iff_existsUnique
code: @[to_additive]
theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
    UniqueMul A B a0 b0 ↔ ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = a0 * b0 
goal: UniqueAdd A B a0 b0 ↔ ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 + ab.2 = a0 + b0

full_name: UniqueMul.iff_existsUnique
code: @[to_additive]
theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
    UniqueMul A B a0 b0 ↔ ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = a0 * b0 
goal: UniqueMul A B a0 b0 ↔ ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = a0 * b0

full_name: UniqueAdd.iff_card_nonpos
code: @[to_additive]
theorem iff_card_le_one [DecidableEq G] (ha0 : a0 ∈ A) (hb0 : b0 ∈ B) :
    UniqueMul A B a0 b0 ↔ ((A ×ˢ B).filter (fun p ↦ p.1 * p.2 = a0 * b0)).card ≤ 1 
goal: UniqueAdd A B a0 b0 ↔ (Finset.filter (fun p => p.1 + p.2 = a0 + b0) (A ×ˢ B)).card ≤ 1

full_name: UniqueMul.iff_card_le_one
code: @[to_additive]
theorem iff_card_le_one [DecidableEq G] (ha0 : a0 ∈ A) (hb0 : b0 ∈ B) :
    UniqueMul A B a0 b0 ↔ ((A ×ˢ B).filter (fun p ↦ p.1 * p.2 = a0 * b0)).card ≤ 1 
goal: UniqueMul A B a0 b0 ↔ (Finset.filter (fun p => p.1 * p.2 = a0 * b0) (A ×ˢ B)).card ≤ 1

full_name: UniqueMul.exists_iff_exists_existsUnique
code: @[to_additive]
theorem exists_iff_exists_existsUnique :
    (∃ a0 b0 : G, a0 ∈ A ∧ b0 ∈ B ∧ UniqueMul A B a0 b0) ↔
      ∃ g : G, ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = g 
goal: (∃ a0 b0, a0 ∈ A ∧ b0 ∈ B ∧ UniqueMul A B a0 b0) ↔ ∃ g, ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = g

full_name: UniqueAdd.exists_iff_exists_existsUnique
code: @[to_additive]
theorem exists_iff_exists_existsUnique :
    (∃ a0 b0 : G, a0 ∈ A ∧ b0 ∈ B ∧ UniqueMul A B a0 b0) ↔
      ∃ g : G, ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = g 
goal: (∃ a0 b0, a0 ∈ A ∧ b0 ∈ B ∧ UniqueAdd A B a0 b0) ↔ ∃ g, ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 + ab.2 = g

full_name: UniqueAdd.addHom_preimage
code: /-- `UniqueMul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`UniqueAdd` is preserved by inverse images under injective, additive maps."]
theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G) {A B : Finset H}
    (u : UniqueMul A B (f a0) (f b0)) :
    UniqueMul (A.preimage f hf.injOn) (B.preimage f hf.injOn) a0 b0 
goal: UniqueAdd (A.preimage ⇑f ⋯) (B.preimage ⇑f ⋯) a0 b0

full_name: UniqueMul.mulHom_preimage
code: /-- `UniqueMul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`UniqueAdd` is preserved by inverse images under injective, additive maps."]
theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G) {A B : Finset H}
    (u : UniqueMul A B (f a0) (f b0)) :
    UniqueMul (A.preimage f hf.injOn) (B.preimage f hf.injOn) a0 b0 
goal: UniqueMul (A.preimage ⇑f ⋯) (B.preimage ⇑f ⋯) a0 b0

full_name: UniqueMul.of_mulHom_image
code: @[to_additive] theorem of_mulHom_image [DecidableEq H] (f : G →ₙ* H)
    (hf : ∀ ⦃a b c d : G⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    (h : UniqueMul (A.image f) (B.image f) (f a0) (f b0)) : UniqueMul A B a0 b0 
goal: UniqueMul A B a0 b0

full_name: UniqueAdd.of_addHom_image
code: @[to_additive] theorem of_mulHom_image [DecidableEq H] (f : G →ₙ* H)
    (hf : ∀ ⦃a b c d : G⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    (h : UniqueMul (A.image f) (B.image f) (f a0) (f b0)) : UniqueMul A B a0 b0 
goal: UniqueAdd A B a0 b0

full_name: UniqueMul.mulHom_image_iff
code: /-- `Unique_Mul` is preserved under multiplicative maps that are injective.

See `UniqueMul.mulHom_map_iff` for a version with swapped bundling. -/
@[to_additive
      "`UniqueAdd` is preserved under additive maps that are injective.

See `UniqueAdd.addHom_map_iff` for a version with swapped bundling."]
theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Injective f) :
    UniqueMul (A.image f) (B.image f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 
goal: UniqueMul (Finset.image (⇑f) A) (Finset.image (⇑f) B) (f a0) (f b0) ↔ UniqueMul A B a0 b0

full_name: UniqueAdd.addHom_image_iff
code: /-- `Unique_Mul` is preserved under multiplicative maps that are injective.

See `UniqueMul.mulHom_map_iff` for a version with swapped bundling. -/
@[to_additive
      "`UniqueAdd` is preserved under additive maps that are injective.

See `UniqueAdd.addHom_map_iff` for a version with swapped bundling."]
theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Injective f) :
    UniqueMul (A.image f) (B.image f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 
goal: UniqueAdd (Finset.image (⇑f) A) (Finset.image (⇑f) B) (f a0) (f b0) ↔ UniqueAdd A B a0 b0

full_name: UniqueAdd.addHom_map_iff
code: /-- `UniqueMul` is preserved under embeddings that are multiplicative.

See `UniqueMul.mulHom_image_iff` for a version with swapped bundling. -/
@[to_additive
      "`UniqueAdd` is preserved under embeddings that are additive.

See `UniqueAdd.addHom_image_iff` for a version with swapped bundling."]
theorem mulHom_map_iff (f : G ↪ H) (mul : ∀ x y, f (x * y) = f x * f y) :
    UniqueMul (A.map f) (B.map f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 
goal: UniqueAdd (Finset.map f A) (Finset.map f B) (f a0) (f b0) ↔ UniqueAdd A B a0 b0

full_name: UniqueMul.mulHom_map_iff
code: /-- `UniqueMul` is preserved under embeddings that are multiplicative.

See `UniqueMul.mulHom_image_iff` for a version with swapped bundling. -/
@[to_additive
      "`UniqueAdd` is preserved under embeddings that are additive.

See `UniqueAdd.addHom_image_iff` for a version with swapped bundling."]
theorem mulHom_map_iff (f : G ↪ H) (mul : ∀ x y, f (x * y) = f x * f y) :
    UniqueMul (A.map f) (B.map f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 
goal: UniqueMul (Finset.map f A) (Finset.map f B) (f a0) (f b0) ↔ UniqueMul A B a0 b0

full_name: UniqueMul.of_mulOpposite
code: @[to_additive]
theorem of_mulOpposite
    (h : UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0)) :
    UniqueMul A B a0 b0 
goal: UniqueMul A B a0 b0

full_name: UniqueAdd.of_addOpposite
code: @[to_additive]
theorem of_mulOpposite
    (h : UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0)) :
    UniqueMul A B a0 b0 
goal: UniqueAdd A B a0 b0

full_name: UniqueAdd.to_addOpposite
code: @[to_additive]
theorem to_mulOpposite (h : UniqueMul A B a0 b0) :
    UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) 
goal: UniqueAdd (Finset.map { toFun := AddOpposite.op, inj' := ⋯ } B) (Finset.map { toFun := AddOpposite.op, inj' := ⋯ } A)
  (AddOpposite.op b0) (AddOpposite.op a0)

full_name: UniqueMul.to_mulOpposite
code: @[to_additive]
theorem to_mulOpposite (h : UniqueMul A B a0 b0) :
    UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) 
goal: UniqueMul (Finset.map { toFun := MulOpposite.op, inj' := ⋯ } B) (Finset.map { toFun := MulOpposite.op, inj' := ⋯ } A)
  (MulOpposite.op b0) (MulOpposite.op a0)

full_name: UniqueMul.iff_mulOpposite
code: @[to_additive]
theorem iff_mulOpposite :
    UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) ↔
      UniqueMul A B a0 b0 
goal: UniqueMul (Finset.map { toFun := MulOpposite.op, inj' := ⋯ } B) (Finset.map { toFun := MulOpposite.op, inj' := ⋯ } A)
    (MulOpposite.op b0) (MulOpposite.op a0) ↔
  UniqueMul A B a0 b0

full_name: UniqueAdd.iff_addOpposite
code: @[to_additive]
theorem iff_mulOpposite :
    UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) ↔
      UniqueMul A B a0 b0 
goal: UniqueAdd (Finset.map { toFun := AddOpposite.op, inj' := ⋯ } B) (Finset.map { toFun := AddOpposite.op, inj' := ⋯ } A)
    (AddOpposite.op b0) (AddOpposite.op a0) ↔
  UniqueAdd A B a0 b0

full_name: UniqueAdd.of_image_filter
code: @[to_additive]
theorem of_image_filter [DecidableEq H]
    (f : G →ₙ* H) {A B : Finset G} {aG bG : G} {aH bH : H} (hae : f aG = aH) (hbe : f bG = bH)
    (huH : UniqueMul (A.image f) (B.image f) aH bH)
    (huG : UniqueMul (A.filter (f · = aH)) (B.filter (f · = bH)) aG bG) :
    UniqueMul A B aG bG 
goal: UniqueAdd A B aG bG

full_name: UniqueMul.of_image_filter
code: @[to_additive]
theorem of_image_filter [DecidableEq H]
    (f : G →ₙ* H) {A B : Finset G} {aG bG : G} {aH bH : H} (hae : f aG = aH) (hbe : f bG = bH)
    (huH : UniqueMul (A.image f) (B.image f) aH bH)
    (huG : UniqueMul (A.filter (f · = aH)) (B.filter (f · = bH)) aG bG) :
    UniqueMul A B aG bG 
goal: UniqueMul A B aG bG

full_name: UniqueSums
code: /-- Let `G` be a Type with addition.  `UniqueSums G` asserts that any two non-empty
finite subsets of `G` have the `UniqueAdd` property, with respect to some element of their
sum `A + B`. -/
class UniqueSums (G) [Add G] : Prop where
/-- For `A B` two nonempty finite sets, there always exist `a0 ∈ A, b0 ∈ B` such that
`UniqueAdd A B a0 b0` -/
  uniqueAdd_of_nonempty :
    ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueAdd A B a0 b0
goal: Prop

full_name: UniqueSums.uniqueAdd_of_nonempty
code: /-- Let `G` be a Type with addition.  `UniqueSums G` asserts that any two non-empty
finite subsets of `G` have the `UniqueAdd` property, with respect to some element of their
sum `A + B`. -/
class UniqueSums (G) [Add G] : Prop where
/-- For `A B` two nonempty finite sets, there always exist `a0 ∈ A, b0 ∈ B` such that
`UniqueAdd A B a0 b0` -/
  uniqueAdd_of_nonempty :
    ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueAdd A B a0 b0
goal: A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueAdd A B a0 b0

full_name: UniqueProds
code: /-- Let `G` be a Type with multiplication.  `UniqueProds G` asserts that any two non-empty
finite subsets of `G` have the `UniqueMul` property, with respect to some element of their
product `A * B`. -/
class UniqueProds (G) [Mul G] : Prop where
/-- For `A B` two nonempty finite sets, there always exist `a0 ∈ A, b0 ∈ B` such that
`UniqueMul A B a0 b0` -/
  uniqueMul_of_nonempty :
    ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0
goal: Prop

full_name: UniqueProds.uniqueMul_of_nonempty
code: /-- Let `G` be a Type with multiplication.  `UniqueProds G` asserts that any two non-empty
finite subsets of `G` have the `UniqueMul` property, with respect to some element of their
product `A * B`. -/
class UniqueProds (G) [Mul G] : Prop where
/-- For `A B` two nonempty finite sets, there always exist `a0 ∈ A, b0 ∈ B` such that
`UniqueMul A B a0 b0` -/
  uniqueMul_of_nonempty :
    ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0
goal: A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0

full_name: TwoUniqueSums
code: /-- Let `G` be a Type with addition. `TwoUniqueSums G` asserts that any two non-empty
finite subsets of `G`, at least one of which is not a singleton, possesses at least two pairs
of elements satisfying the `UniqueAdd` property. -/
class TwoUniqueSums (G) [Add G] : Prop where
/-- For `A B` two finite sets whose product has cardinality at least 2,
  we can find at least two unique pairs. -/
  uniqueAdd_of_one_lt_card : ∀ {A B : Finset G}, 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueAdd A B p1.1 p1.2 ∧ UniqueAdd A B p2.1 p2.2
goal: Prop

full_name: TwoUniqueSums.uniqueAdd_of_one_lt_card
code: /-- Let `G` be a Type with addition. `TwoUniqueSums G` asserts that any two non-empty
finite subsets of `G`, at least one of which is not a singleton, possesses at least two pairs
of elements satisfying the `UniqueAdd` property. -/
class TwoUniqueSums (G) [Add G] : Prop where
/-- For `A B` two finite sets whose product has cardinality at least 2,
  we can find at least two unique pairs. -/
  uniqueAdd_of_one_lt_card : ∀ {A B : Finset G}, 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueAdd A B p1.1 p1.2 ∧ UniqueAdd A B p2.1 p2.2
goal: 1 < A.card * B.card → ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueAdd A B p1.1 p1.2 ∧ UniqueAdd A B p2.1 p2.2

full_name: TwoUniqueProds
code: /-- Let `G` be a Type with multiplication. `TwoUniqueProds G` asserts that any two non-empty
finite subsets of `G`, at least one of which is not a singleton, possesses at least two pairs
of elements satisfying the `UniqueMul` property. -/
class TwoUniqueProds (G) [Mul G] : Prop where
/-- For `A B` two finite sets whose product has cardinality at least 2,
  we can find at least two unique pairs. -/
  uniqueMul_of_one_lt_card : ∀ {A B : Finset G}, 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2
goal: Prop

full_name: TwoUniqueProds.uniqueMul_of_one_lt_card
code: /-- Let `G` be a Type with multiplication. `TwoUniqueProds G` asserts that any two non-empty
finite subsets of `G`, at least one of which is not a singleton, possesses at least two pairs
of elements satisfying the `UniqueMul` property. -/
class TwoUniqueProds (G) [Mul G] : Prop where
/-- For `A B` two finite sets whose product has cardinality at least 2,
  we can find at least two unique pairs. -/
  uniqueMul_of_one_lt_card : ∀ {A B : Finset G}, 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2
goal: 1 < A.card * B.card → ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2

full_name: uniqueMul_of_twoUniqueMul
code: @[to_additive]
lemma uniqueMul_of_twoUniqueMul {G} [Mul G] {A B : Finset G} (h : 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2)
    (hA : A.Nonempty) (hB : B.Nonempty) : ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b 
goal: ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b

full_name: uniqueAdd_of_twoUniqueAdd
code: @[to_additive]
lemma uniqueMul_of_twoUniqueMul {G} [Mul G] {A B : Finset G} (h : 1 < A.card * B.card →
    ∃ p1 ∈ A ×ˢ B, ∃ p2 ∈ A ×ˢ B, p1 ≠ p2 ∧ UniqueMul A B p1.1 p1.2 ∧ UniqueMul A B p2.1 p2.2)
    (hA : A.Nonempty) (hB : B.Nonempty) : ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b 
goal: ∃ a ∈ A, ∃ b ∈ B, UniqueAdd A B a b

full_name: TwoUniqueSums.toUniqueSums
code: @[to_additive] instance TwoUniqueProds.toUniqueProds (G) [Mul G] [TwoUniqueProds G] :
    UniqueProds G 
goal: UniqueSums G

full_name: TwoUniqueProds.toUniqueProds
code: @[to_additive] instance TwoUniqueProds.toUniqueProds (G) [Mul G] [TwoUniqueProds G] :
    UniqueProds G 
goal: UniqueProds G

full_name: Multiplicative.instUniqueProdsOfUniqueSums
code: instance {M} [Add M] [UniqueSums M] : UniqueProds (Multiplicative M) 
goal: UniqueProds (Multiplicative M)

full_name: Multiplicative.instTwoUniqueProdsOfTwoUniqueSums
code: instance {M} [Add M] [TwoUniqueSums M] : TwoUniqueProds (Multiplicative M) 
goal: TwoUniqueProds (Multiplicative M)

full_name: Additive.instUniqueSumsOfUniqueProds
code: instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M) 
goal: UniqueSums (Additive M)

full_name: Additive.instTwoUniqueSumsOfTwoUniqueProds
code: instance {M} [Mul M] [TwoUniqueProds M] : TwoUniqueSums (Additive M) 
goal: TwoUniqueSums (Additive M)

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.I
code: private abbrev I : Bool → Type max u v 
goal: Bool → Type (max u v)

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.instMulI
code: @[to_additive] private instance : ∀ b, Mul (I G H b) 
goal: Mul (I G H b)

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.instAddI
code: @[to_additive] private instance : ∀ b, Mul (I G H b) 
goal: Add (I G H b)

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.Prod.upMulHom
code: @[to_additive] private def Prod.upMulHom : G × H →ₙ* ∀ b, I G H b 
goal: G × H →ₙ* (b : Bool) → I G H b

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.Prod.upAddHom
code: @[to_additive] private def Prod.upMulHom : G × H →ₙ* ∀ b, I G H b 
goal: AddHom (G × H) ((b : Bool) → I G H b)

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.downMulHom
code: @[to_additive] private def downMulHom : ULift G →ₙ* G 
goal: ULift.{u_1, u} G →ₙ* G

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.downAddHom
code: @[to_additive] private def downMulHom : ULift G →ₙ* G 
goal: AddHom (ULift.{u_1, u} G) G

full_name: UniqueSums.of_addHom
code: @[to_additive] theorem of_mulHom (f : H →ₙ* G)
    (hf : ∀ ⦃a b c d : H⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    [UniqueProds G] : UniqueProds H 
goal: UniqueSums H

full_name: UniqueProds.of_mulHom
code: @[to_additive] theorem of_mulHom (f : H →ₙ* G)
    (hf : ∀ ⦃a b c d : H⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    [UniqueProds G] : UniqueProds H 
goal: UniqueProds H

full_name: UniqueSums.of_injective_addHom
code: @[to_additive]
theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f) (_ : UniqueProds G) :
    UniqueProds H 
goal: UniqueSums G → UniqueSums H

full_name: UniqueProds.of_injective_mulHom
code: @[to_additive]
theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f) (_ : UniqueProds G) :
    UniqueProds H 
goal: UniqueProds G → UniqueProds H

full_name: AddEquiv.uniqueSums_iff
code: /-- `UniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`UniqueSums` is preserved under additive equivalences."]
theorem _root_.MulEquiv.uniqueProds_iff (f : G ≃* H) : UniqueProds G ↔ UniqueProds H 
goal: UniqueSums G ↔ UniqueSums H

full_name: MulEquiv.uniqueProds_iff
code: /-- `UniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`UniqueSums` is preserved under additive equivalences."]
theorem _root_.MulEquiv.uniqueProds_iff (f : G ≃* H) : UniqueProds G ↔ UniqueProds H 
goal: UniqueProds G ↔ UniqueProds H

full_name: UniqueProds.of_mulOpposite
code: @[to_additive]
theorem of_mulOpposite (h : UniqueProds Gᵐᵒᵖ) : UniqueProds G 
goal: UniqueProds G

full_name: UniqueSums.of_addOpposite
code: @[to_additive]
theorem of_mulOpposite (h : UniqueProds Gᵐᵒᵖ) : UniqueProds G 
goal: UniqueSums G

full_name: UniqueSums.instAddOpposite
code: @[to_additive] instance [h : UniqueProds G] : UniqueProds Gᵐᵒᵖ 
goal: UniqueSums Gᵃᵒᵖ

full_name: UniqueProds.instMulOpposite
code: @[to_additive] instance [h : UniqueProds G] : UniqueProds Gᵐᵒᵖ 
goal: UniqueProds Gᵐᵒᵖ

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.UniqueProds.toIsAddLeftCancel
code: @[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G 
goal: IsLeftCancelAdd G

full_name: _private.Mathlib.Algebra.Group.UniqueProds.0.UniqueProds.toIsLeftCancelMul
code: @[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G 
goal: IsLeftCancelMul G

full_name: UniqueSums.toIsAddCancel
code: @[to_additive] theorem toIsCancelMul [UniqueProds G] : IsCancelMul G 
goal: IsCancelAdd G

full_name: UniqueProds.toIsCancelMul
code: @[to_additive] theorem toIsCancelMul [UniqueProds G] : IsCancelMul G 
goal: IsCancelMul G

full_name: UniqueSums.of_same
code: /-- `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 
goal: UniqueSums G

full_name: UniqueProds.of_same
code: /-- `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 
goal: UniqueProds G

full_name: UniqueSums.toTwoUniqueSums_of_addGroup
code: /-- 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 
goal: TwoUniqueSums G

full_name: UniqueProds.toTwoUniqueProds_of_group
code: /-- 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 
goal: TwoUniqueProds G

full_name: UniqueProds.instForall
code: @[to_additive] instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
    UniqueProds (∀ i, G i) 
goal: UniqueProds ((i : ι) → G i)

full_name: UniqueSums.instForall
code: @[to_additive] instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
    UniqueProds (∀ i, G i) 
goal: UniqueSums ((i : ι) → G i)

full_name: UniqueSums.instSum
code: @[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) 
goal: UniqueSums (G × H)

full_name: UniqueProds.instProd
code: @[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) 
goal: UniqueProds (G × H)

full_name: instUniqueSumsDFinsupp
code: instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums (G i)] :
    UniqueSums (Π₀ i, G i) 
goal: UniqueSums (Π₀ (i : ι), G i)

full_name: instUniqueSumsFinsupp
code: instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) 
goal: UniqueSums (ι →₀ G)

full_name: TwoUniqueProds.of_mulHom
code: @[to_additive] theorem of_mulHom (f : H →ₙ* G)
    (hf : ∀ ⦃a b c d : H⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    [TwoUniqueProds G] : TwoUniqueProds H 
goal: TwoUniqueProds H

full_name: TwoUniqueSums.of_addHom
code: @[to_additive] theorem of_mulHom (f : H →ₙ* G)
    (hf : ∀ ⦃a b c d : H⦄, a * b = c * d → f a = f c ∧ f b = f d → a = c ∧ b = d)
    [TwoUniqueProds G] : TwoUniqueProds H 
goal: TwoUniqueSums H

full_name: TwoUniqueSums.of_injective_addHom
code: @[to_additive]
theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f)
    (_ : TwoUniqueProds G) : TwoUniqueProds H 
goal: TwoUniqueSums G → TwoUniqueSums H

full_name: TwoUniqueProds.of_injective_mulHom
code: @[to_additive]
theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f)
    (_ : TwoUniqueProds G) : TwoUniqueProds H 
goal: TwoUniqueProds G → TwoUniqueProds H

full_name: AddEquiv.twoUniqueSums_iff
code: /-- `TwoUniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`TwoUniqueSums` is preserved under additive equivalences."]
theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H 
goal: TwoUniqueSums G ↔ TwoUniqueSums H

full_name: MulEquiv.twoUniqueProds_iff
code: /-- `TwoUniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`TwoUniqueSums` is preserved under additive equivalences."]
theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H 
goal: TwoUniqueProds G ↔ TwoUniqueProds H

full_name: TwoUniqueSums.instForall
code: @[to_additive]
instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
    TwoUniqueProds (∀ i, G i) 
goal: TwoUniqueSums ((i : ι) → G i)

full_name: TwoUniqueProds.instForall
code: @[to_additive]
instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
    TwoUniqueProds (∀ i, G i) 
goal: TwoUniqueProds ((i : ι) → G i)

full_name: TwoUniqueProds.instProd
code: @[to_additive] instance [TwoUniqueProds G] [TwoUniqueProds H] : TwoUniqueProds (G × H) 
goal: TwoUniqueProds (G × H)

full_name: TwoUniqueSums.instSum
code: @[to_additive] instance [TwoUniqueProds G] [TwoUniqueProds H] : TwoUniqueProds (G × H) 
goal: TwoUniqueSums (G × H)

full_name: TwoUniqueSums.of_addOpposite
code: @[to_additive]
theorem of_mulOpposite (h : TwoUniqueProds Gᵐᵒᵖ) : TwoUniqueProds G 
goal: TwoUniqueSums G

full_name: TwoUniqueProds.of_mulOpposite
code: @[to_additive]
theorem of_mulOpposite (h : TwoUniqueProds Gᵐᵒᵖ) : TwoUniqueProds G 
goal: TwoUniqueProds G

full_name: TwoUniqueSums.instAddOpposite
code: @[to_additive] instance [h : TwoUniqueProds G] : TwoUniqueProds Gᵐᵒᵖ 
goal: TwoUniqueSums Gᵃᵒᵖ

full_name: TwoUniqueProds.instMulOpposite
code: @[to_additive] instance [h : TwoUniqueProds G] : TwoUniqueProds Gᵐᵒᵖ 
goal: TwoUniqueProds Gᵐᵒᵖ

full_name: TwoUniqueSums.of_covariant_right
code: /-- This instance asserts that if `G` has a right-cancellative multiplication, a linear order, and
  multiplication is strictly monotone w.r.t. the second argument, then `G` has `TwoUniqueProds`. -/
@[to_additive
  "This instance asserts that if `G` has a right-cancellative addition, a linear order,
  and addition is strictly monotone w.r.t. the second argument, then `G` has `TwoUniqueSums`." ]
instance (priority := 100) of_covariant_right [IsRightCancelMul G]
    [LinearOrder G] [CovariantClass G G (· * ·) (· < ·)] :
    TwoUniqueProds G 
goal: TwoUniqueSums G

full_name: TwoUniqueProds.of_covariant_right
code: /-- This instance asserts that if `G` has a right-cancellative multiplication, a linear order, and
  multiplication is strictly monotone w.r.t. the second argument, then `G` has `TwoUniqueProds`. -/
@[to_additive
  "This instance asserts that if `G` has a right-cancellative addition, a linear order,
  and addition is strictly monotone w.r.t. the second argument, then `G` has `TwoUniqueSums`." ]
instance (priority := 100) of_covariant_right [IsRightCancelMul G]
    [LinearOrder G] [CovariantClass G G (· * ·) (· < ·)] :
    TwoUniqueProds G 
goal: TwoUniqueProds G

full_name: TwoUniqueProds.of_covariant_left
code: /-- This instance asserts that if `G` has a left-cancellative multiplication, a linear order, and
  multiplication is strictly monotone w.r.t. the first argument, then `G` has `TwoUniqueProds`. -/
@[to_additive
  "This instance asserts that if `G` has a left-cancellative addition, a linear order, and
  addition is strictly monotone w.r.t. the first argument, then `G` has `TwoUniqueSums`." ]
instance (priority := 100) of_covariant_left [IsLeftCancelMul G]
    [LinearOrder G] [CovariantClass G G (Function.swap (· * ·)) (· < ·)] :
    TwoUniqueProds G 
goal: TwoUniqueProds G

full_name: TwoUniqueSums.of_covariant_left
code: /-- This instance asserts that if `G` has a left-cancellative multiplication, a linear order, and
  multiplication is strictly monotone w.r.t. the first argument, then `G` has `TwoUniqueProds`. -/
@[to_additive
  "This instance asserts that if `G` has a left-cancellative addition, a linear order, and
  addition is strictly monotone w.r.t. the first argument, then `G` has `TwoUniqueSums`." ]
instance (priority := 100) of_covariant_left [IsLeftCancelMul G]
    [LinearOrder G] [CovariantClass G G (Function.swap (· * ·)) (· < ·)] :
    TwoUniqueProds G 
goal: TwoUniqueSums G

full_name: instTwoUniqueSumsDFinsupp
code: instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] :
    TwoUniqueSums (Π₀ i, G i) 
goal: TwoUniqueSums (Π₀ (i : ι), G i)

full_name: instTwoUniqueSumsFinsupp
code: instance {ι G} [AddZeroClass G] [TwoUniqueSums G] : TwoUniqueSums (ι →₀ G) 
goal: TwoUniqueSums (ι →₀ G)

full_name: instTwoUniqueSumsOfModuleRat
code: /-- Any `ℚ`-vector space has `TwoUniqueSums`, because it is isomorphic to some
  `(Basis.ofVectorSpaceIndex ℚ G) →₀ ℚ` by choosing a basis, and `ℚ` already has
  `TwoUniqueSums` because it's ordered. -/
instance [AddCommGroup G] [Module ℚ G] : TwoUniqueSums G 
goal: TwoUniqueSums G

full_name: FreeMonoid.instTwoUniqueProds
code: /-- Any `FreeMonoid` has the `TwoUniqueProds` property. -/
instance FreeMonoid.instTwoUniqueProds {κ : Type*} : TwoUniqueProds (FreeMonoid κ) 
goal: TwoUniqueProds (FreeMonoid κ)

full_name: FreeAddMonoid.instTwoUniqueSums
code: /-- Any `FreeAddMonoid` has the `TwoUniqueSums` property. -/
instance FreeAddMonoid.instTwoUniqueSums {κ : Type*} : TwoUniqueSums (FreeAddMonoid κ) 
goal: TwoUniqueSums (FreeAddMonoid κ)