algebra.group.unique_prods
⟷
Mathlib.Algebra.Group.UniqueProds
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -84,7 +84,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#align unique_add.set_subsingleton UniqueAdd.set_subsingleton
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
@[to_additive]
theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
@@ -98,7 +98,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
#align unique_mul.iff_exists_unique UniqueMul.iff_existsUniqueₓ
#align unique_add.iff_exists_unique UniqueAdd.iff_existsUniqueₓ
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
@[to_additive]
theorem exists_iff_exists_existsUnique :
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -123,7 +123,7 @@ theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G
by
intro a b ha hb ab
rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
+ rw [← hf.eq_iff, map_mul, map_mul] at ab
exact u (finset.mem_preimage.mp ha) (finset.mem_preimage.mp hb) ab
#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimage
#align unique_add.add_hom_preimage UniqueAdd.addHom_preimage
@@ -141,13 +141,13 @@ theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Inject
refine' ⟨fun h => _, fun h => _⟩
· intro a b ha hb ab
rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
+ rw [← hf.eq_iff, map_mul, map_mul] at ab
exact h (finset.mem_image.mpr ⟨_, ha, rfl⟩) (finset.mem_image.mpr ⟨_, hb, rfl⟩) ab
· intro a b aA bB ab
obtain ⟨a, ha, rfl⟩ : ∃ a' ∈ A, f a' = a := finset.mem_image.mp aA
obtain ⟨b, hb, rfl⟩ : ∃ b' ∈ B, f b' = b := finset.mem_image.mp bB
rw [hf.eq_iff, hf.eq_iff]
- rw [← map_mul, ← map_mul, hf.eq_iff] at ab
+ rw [← map_mul, ← map_mul, hf.eq_iff] at ab
exact h ha hb ab
#align unique_mul.mul_hom_image_iff UniqueMul.mulHom_image_iff
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
@@ -225,7 +225,7 @@ theorem eq_and_eq_of_le_of_le_of_hMul_le {A} [Mul A] [LinearOrder A]
haveI := Mul.to_covariantClass_right A
have ha' : ¬a0 * b0 < a * b → ¬a0 < a := mt fun h => mul_lt_mul_of_lt_of_le h hb
have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h => mul_lt_mul_of_le_of_lt ha h
- push_neg at ha' hb'
+ push_neg at ha' hb'
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_hMul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -160,7 +160,10 @@ See `unique_mul.mul_hom_image_iff` for a version with swapped bundling. -/
@[to_additive
"`unique_add` is preserved under embeddings that are additive.\n\nSee `unique_add.add_hom_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 := by classical
+ UniqueMul (A.map f) (B.map f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 := by
+ classical convert mul_hom_image_iff ⟨f, mul⟩ f.2 <;>
+ · ext
+ simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -160,10 +160,7 @@ See `unique_mul.mul_hom_image_iff` for a version with swapped bundling. -/
@[to_additive
"`unique_add` is preserved under embeddings that are additive.\n\nSee `unique_add.add_hom_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 := by
- classical convert mul_hom_image_iff ⟨f, mul⟩ f.2 <;>
- · ext
- simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
+ UniqueMul (A.map f) (B.map f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 := by classical
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,7 +3,7 @@ Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa
-/
-import Mathbin.Data.Finset.Preimage
+import Data.Finset.Preimage
#align_import algebra.group.unique_prods from "leanprover-community/mathlib"@"63f84d91dd847f50bae04a01071f3a5491934e36"
@@ -84,7 +84,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#align unique_add.set_subsingleton UniqueAdd.set_subsingleton
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
@[to_additive]
theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
@@ -98,7 +98,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
#align unique_mul.iff_exists_unique UniqueMul.iff_existsUniqueₓ
#align unique_add.iff_exists_unique UniqueAdd.iff_existsUniqueₓ
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
@[to_additive]
theorem exists_iff_exists_existsUnique :
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -86,7 +86,6 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
-#print UniqueMul.iff_existsUnique /-
@[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 :=
@@ -96,13 +95,11 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
rintro ⟨x1, x2⟩ _ _ J x y hx hy l
rcases prod.mk.inj_iff.mp (J (a0, b0) (Finset.mk_mem_product aA bB) rfl) with ⟨rfl, rfl⟩
exact prod.mk.inj_iff.mp (J (x, y) (Finset.mk_mem_product hx hy) l))⟩
-#align unique_mul.iff_exists_unique UniqueMul.iff_existsUnique
-#align unique_add.iff_exists_unique UniqueAdd.iff_existsUnique
--/
+#align unique_mul.iff_exists_unique UniqueMul.iff_existsUniqueₓ
+#align unique_add.iff_exists_unique UniqueAdd.iff_existsUniqueₓ
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
-#print UniqueMul.exists_iff_exists_existsUnique /-
@[to_additive]
theorem exists_iff_exists_existsUnique :
(∃ a0 b0 : G, a0 ∈ A ∧ b0 ∈ B ∧ UniqueMul A B a0 b0) ↔
@@ -113,9 +110,8 @@ theorem exists_iff_exists_existsUnique :
rcases h' with ⟨⟨a, b⟩, ⟨hab, rfl, -⟩, -⟩
cases' finset.mem_product.mp hab with ha hb
exact ⟨a, b, ha, hb, (iff_exists_unique ha hb).mpr h⟩⟩
-#align unique_mul.exists_iff_exists_exists_unique UniqueMul.exists_iff_exists_existsUnique
-#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUnique
--/
+#align unique_mul.exists_iff_exists_exists_unique UniqueMul.exists_iff_exists_existsUniqueₓ
+#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUniqueₓ
#print UniqueMul.mulHom_preimage /-
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
mathlib commit https://github.com/leanprover-community/mathlib/commit/001ffdc42920050657fd45bd2b8bfbec8eaaeb29
@@ -220,9 +220,8 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M)
end Additive
-#print eq_and_eq_of_le_of_le_of_mul_le /-
@[to_additive]
-theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
+theorem eq_and_eq_of_le_of_le_of_hMul_le {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
[ContravariantClass A A (· * ·) (· ≤ ·)] {a b a0 b0 : A} (ha : a0 ≤ a) (hb : b0 ≤ b)
(ab : a * b ≤ a0 * b0) : a = a0 ∧ b = b0 :=
@@ -232,11 +231,9 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h => mul_lt_mul_of_le_of_lt ha h
push_neg at ha' hb'
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
-#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
+#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_hMul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
--/
-#print Covariants.to_uniqueProds /-
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `unique_prods`. -/
@@ -247,8 +244,7 @@ instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
[ContravariantClass A A (· * ·) (· ≤ ·)] : UniqueProds A
where uniqueMul_of_nonempty A B hA hB :=
⟨_, A.min'_mem ‹_›, _, B.min'_mem ‹_›, fun a b ha hb ab =>
- eq_and_eq_of_le_of_le_of_mul_le (Finset.min'_le _ _ ‹_›) (Finset.min'_le _ _ ‹_›) ab.le⟩
+ eq_and_eq_of_le_of_le_of_hMul_le (Finset.min'_le _ _ ‹_›) (Finset.min'_le _ _ ‹_›) ab.le⟩
#align covariants.to_unique_prods Covariants.to_uniqueProds
-#align covariants.to_unique_sums Covariants.to_uniqueSums
--/
+#align covariants.to_unique_sums Covariants.to_unique_sums
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,14 +2,11 @@
Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa
-
-! This file was ported from Lean 3 source module algebra.group.unique_prods
-! leanprover-community/mathlib commit 63f84d91dd847f50bae04a01071f3a5491934e36
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.Finset.Preimage
+#align_import algebra.group.unique_prods from "leanprover-community/mathlib"@"63f84d91dd847f50bae04a01071f3a5491934e36"
+
/-!
# Unique products and related notions
@@ -87,7 +84,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#align unique_add.set_subsingleton UniqueAdd.set_subsingleton
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.iff_existsUnique /-
@[to_additive]
@@ -103,7 +100,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
#align unique_add.iff_exists_unique UniqueAdd.iff_existsUnique
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.exists_iff_exists_existsUnique /-
@[to_additive]
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -120,6 +120,7 @@ theorem exists_iff_exists_existsUnique :
#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUnique
-/
+#print UniqueMul.mulHom_preimage /-
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` 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}
@@ -133,6 +134,7 @@ theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G
exact u (finset.mem_preimage.mp ha) (finset.mem_preimage.mp hb) ab
#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimage
#align unique_add.add_hom_preimage UniqueAdd.addHom_preimage
+-/
#print UniqueMul.mulHom_image_iff /-
/-- `unique_mul` is preserved under multiplicative maps that are injective.
@@ -158,6 +160,7 @@ theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Inject
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
-/
+#print UniqueMul.mulHom_map_iff /-
/-- `unique_mul` is preserved under embeddings that are multiplicative.
See `unique_mul.mul_hom_image_iff` for a version with swapped bundling. -/
@@ -170,6 +173,7 @@ theorem mulHom_map_iff (f : G ↪ H) (mul : ∀ x y, f (x * y) = f x * f y) :
simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
+-/
end UniqueMul
mathlib commit https://github.com/leanprover-community/mathlib/commit/31c24aa72e7b3e5ed97a8412470e904f82b81004
@@ -87,7 +87,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#align unique_add.set_subsingleton UniqueAdd.set_subsingleton
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.iff_existsUnique /-
@[to_additive]
@@ -103,7 +103,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
#align unique_add.iff_exists_unique UniqueAdd.iff_existsUnique
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.exists_iff_exists_existsUnique /-
@[to_additive]
mathlib commit https://github.com/leanprover-community/mathlib/commit/5f25c089cb34db4db112556f23c50d12da81b297
@@ -76,7 +76,7 @@ theorem subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0) :
#print UniqueMul.set_subsingleton /-
@[to_additive]
theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0) :
- Set.Subsingleton { ab : G × G | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } :=
+ Set.Subsingleton {ab : G × G | ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0} :=
by
rintro ⟨x1, y1⟩ (hx : x1 ∈ A ∧ y1 ∈ B ∧ x1 * y1 = a0 * b0) ⟨x2, y2⟩
(hy : x2 ∈ A ∧ y2 ∈ B ∧ x2 * y2 = a0 * b0)
@@ -166,8 +166,8 @@ See `unique_mul.mul_hom_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 := by
classical convert mul_hom_image_iff ⟨f, mul⟩ f.2 <;>
- · ext
- simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
+ · ext
+ simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
@@ -229,7 +229,7 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
haveI := Mul.to_covariantClass_right A
have ha' : ¬a0 * b0 < a * b → ¬a0 < a := mt fun h => mul_lt_mul_of_lt_of_le h hb
have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h => mul_lt_mul_of_le_of_lt ha h
- push_neg at ha' hb'
+ push_neg at ha' hb'
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -92,7 +92,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#print UniqueMul.iff_existsUnique /-
@[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 :=
+ UniqueMul A B a0 b0 ↔ ∃! (ab : _) (_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = a0 * b0 :=
⟨fun _ => ⟨(a0, b0), ⟨Finset.mem_product.mpr ⟨aA, bB⟩, rfl, by simp⟩, by simpa⟩, fun h =>
h.elim₂
(by
@@ -109,7 +109,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
@[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 :=
+ ∃ g : G, ∃! (ab : _) (_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = g :=
⟨fun ⟨a0, b0, hA, hB, h⟩ => ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ =>
by
have h' := h
@@ -129,7 +129,7 @@ theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G
by
intro a b ha hb ab
rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
+ rw [← hf.eq_iff, map_mul, map_mul] at ab
exact u (finset.mem_preimage.mp ha) (finset.mem_preimage.mp hb) ab
#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimage
#align unique_add.add_hom_preimage UniqueAdd.addHom_preimage
@@ -146,13 +146,13 @@ theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Inject
refine' ⟨fun h => _, fun h => _⟩
· intro a b ha hb ab
rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
+ rw [← hf.eq_iff, map_mul, map_mul] at ab
exact h (finset.mem_image.mpr ⟨_, ha, rfl⟩) (finset.mem_image.mpr ⟨_, hb, rfl⟩) ab
· intro a b aA bB ab
obtain ⟨a, ha, rfl⟩ : ∃ a' ∈ A, f a' = a := finset.mem_image.mp aA
obtain ⟨b, hb, rfl⟩ : ∃ b' ∈ B, f b' = b := finset.mem_image.mp bB
rw [hf.eq_iff, hf.eq_iff]
- rw [← map_mul, ← map_mul, hf.eq_iff] at ab
+ rw [← map_mul, ← map_mul, hf.eq_iff] at ab
exact h ha hb ab
#align unique_mul.mul_hom_image_iff UniqueMul.mulHom_image_iff
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
@@ -229,7 +229,7 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
haveI := Mul.to_covariantClass_right A
have ha' : ¬a0 * b0 < a * b → ¬a0 < a := mt fun h => mul_lt_mul_of_lt_of_le h hb
have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h => mul_lt_mul_of_le_of_lt ha h
- push_neg at ha' hb'
+ push_neg at ha' hb'
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -219,6 +219,7 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M)
end Additive
+#print eq_and_eq_of_le_of_le_of_mul_le /-
@[to_additive]
theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
@@ -232,7 +233,9 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
+-/
+#print Covariants.to_uniqueProds /-
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `unique_prods`. -/
@@ -246,4 +249,5 @@ instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
eq_and_eq_of_le_of_le_of_mul_le (Finset.min'_le _ _ ‹_›) (Finset.min'_le _ _ ‹_›) ab.le⟩
#align covariants.to_unique_prods Covariants.to_uniqueProds
#align covariants.to_unique_sums Covariants.to_uniqueSums
+-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -120,9 +120,6 @@ theorem exists_iff_exists_existsUnique :
#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUnique
-/
-/- warning: unique_mul.mul_hom_preimage -> UniqueMul.mulHom_preimage is a dubious translation:
-<too large>
-Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimageₓ'. -/
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` 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}
@@ -161,12 +158,6 @@ theorem mulHom_image_iff [DecidableEq H] (f : G →ₙ* H) (hf : Function.Inject
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
-/
-/- warning: unique_mul.mul_hom_map_iff -> UniqueMul.mulHom_map_iff is a dubious translation:
-lean 3 declaration is
- forall {G : Type.{u1}} {H : Type.{u2}} [_inst_1 : Mul.{u1} G] [_inst_2 : Mul.{u2} H] {A : Finset.{u1} G} {B : Finset.{u1} G} {a0 : G} {b0 : G} (f : Function.Embedding.{succ u1, succ u2} G H), (forall (x : G) (y : G), Eq.{succ u2} H (coeFn.{max 1 (succ u1) (succ u2), max (succ u1) (succ u2)} (Function.Embedding.{succ u1, succ u2} G H) (fun (_x : Function.Embedding.{succ u1, succ u2} G H) => G -> H) (Function.Embedding.hasCoeToFun.{succ u1, succ u2} G H) f (HMul.hMul.{u1, u1, u1} G G G (instHMul.{u1} G _inst_1) x y)) (HMul.hMul.{u2, u2, u2} H H H (instHMul.{u2} H _inst_2) (coeFn.{max 1 (succ u1) (succ u2), max (succ u1) (succ u2)} (Function.Embedding.{succ u1, succ u2} G H) (fun (_x : Function.Embedding.{succ u1, succ u2} G H) => G -> H) (Function.Embedding.hasCoeToFun.{succ u1, succ u2} G H) f x) (coeFn.{max 1 (succ u1) (succ u2), max (succ u1) (succ u2)} (Function.Embedding.{succ u1, succ u2} G H) (fun (_x : Function.Embedding.{succ u1, succ u2} G H) => G -> H) (Function.Embedding.hasCoeToFun.{succ u1, succ u2} G H) f y))) -> (Iff (UniqueMul.{u2} H _inst_2 (Finset.map.{u1, u2} G H f A) (Finset.map.{u1, u2} G H f B) (coeFn.{max 1 (succ u1) (succ u2), max (succ u1) (succ u2)} (Function.Embedding.{succ u1, succ u2} G H) (fun (_x : Function.Embedding.{succ u1, succ u2} G H) => G -> H) (Function.Embedding.hasCoeToFun.{succ u1, succ u2} G H) f a0) (coeFn.{max 1 (succ u1) (succ u2), max (succ u1) (succ u2)} (Function.Embedding.{succ u1, succ u2} G H) (fun (_x : Function.Embedding.{succ u1, succ u2} G H) => G -> H) (Function.Embedding.hasCoeToFun.{succ u1, succ u2} G H) f b0)) (UniqueMul.{u1} G _inst_1 A B a0 b0))
-but is expected to have type
- forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] {A : Finset.{u2} G} {B : Finset.{u2} G} {a0 : G} {b0 : G} (f : Function.Embedding.{succ u2, succ u1} G H), (forall (x : G) (y : G), Eq.{succ u1} ((fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) (HMul.hMul.{u2, u2, u2} G G G (instHMul.{u2} G _inst_1) x y)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G (fun (_x : G) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G H (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} G H)) f (HMul.hMul.{u2, u2, u2} G G G (instHMul.{u2} G _inst_1) x y)) (HMul.hMul.{u1, u1, u1} ((fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) x) ((fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) y) ((fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) x) (instHMul.{u1} ((fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) x) _inst_2) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G (fun (_x : G) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G H (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} G H)) f x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G (fun (_x : G) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G H (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} G H)) f y))) -> (Iff (UniqueMul.{u1} H _inst_2 (Finset.map.{u2, u1} G H f A) (Finset.map.{u2, u1} G H f B) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G (fun (_x : G) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G H (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} G H)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G (fun (_x : G) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : G) => H) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} G H) G H (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} G H)) f b0)) (UniqueMul.{u2} G _inst_1 A B a0 b0))
-Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iffₓ'. -/
/-- `unique_mul` is preserved under embeddings that are multiplicative.
See `unique_mul.mul_hom_image_iff` for a version with swapped bundling. -/
@@ -228,12 +219,6 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M)
end Additive
-/- warning: eq_and_eq_of_le_of_le_of_mul_le -> eq_and_eq_of_le_of_le_of_mul_le is a dubious translation:
-lean 3 declaration is
- forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1))) (LT.lt.{u1} A (Preorder.toHasLt.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_5 : ContravariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] {a : A} {b : A} {a0 : A} {b0 : A}, (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) a0 a) -> (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) b0 b) -> (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a b) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a0 b0)) -> (And (Eq.{succ u1} A a a0) (Eq.{succ u1} A b b0))
-but is expected to have type
- forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1830 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1832 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1830 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1832) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1845 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1847 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1845 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1847)] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1867 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1869 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1867 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1869)) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1882 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1884 : A) => LT.lt.{u1} A (Preorder.toLT.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1882 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1884)] [_inst_5 : ContravariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1901 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1903 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1901 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1903) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1916 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1918 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1916 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1918)] {a : A} {b : A} {a0 : A} {b0 : A}, (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) a0 a) -> (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) b0 b) -> (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a b) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a0 b0)) -> (And (Eq.{succ u1} A a a0) (Eq.{succ u1} A b b0))
-Case conversion may be inaccurate. Consider using '#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_leₓ'. -/
@[to_additive]
theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
@@ -248,12 +233,6 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
-/- warning: covariants.to_unique_prods -> Covariants.to_uniqueProds is a dubious translation:
-lean 3 declaration is
- forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1))) (LT.lt.{u1} A (Preorder.toHasLt.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_5 : ContravariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))], UniqueProds.{u1} A _inst_1
-but is expected to have type
- forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2108 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2110 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2108 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2110) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2123 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2125 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2123 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2125)] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2145 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2147 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2145 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2147)) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2160 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2162 : A) => LT.lt.{u1} A (Preorder.toLT.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2160 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2162)] [_inst_5 : ContravariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2179 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2181 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2179 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2181) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2194 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2196 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2194 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2196)], UniqueProds.{u1} A _inst_1
-Case conversion may be inaccurate. Consider using '#align covariants.to_unique_prods Covariants.to_uniqueProdsₓ'. -/
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `unique_prods`. -/
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -56,10 +56,8 @@ variable {G H : Type _} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
#print UniqueMul.mt /-
theorem mt {G} [Mul G] {A B : Finset G} {a0 b0 : G} (h : UniqueMul A B a0 b0) :
- ∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k =>
- by
- contrapose! k
- exact h ha hb k
+ ∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k => by
+ contrapose! k; exact h ha hb k
#align unique_mul.mt UniqueMul.mt
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -123,10 +123,7 @@ theorem exists_iff_exists_existsUnique :
-/
/- warning: unique_mul.mul_hom_preimage -> UniqueMul.mulHom_preimage is a dubious translation:
-lean 3 declaration is
- forall {G : Type.{u1}} {H : Type.{u2}} [_inst_1 : Mul.{u1} G] [_inst_2 : Mul.{u2} H] (f : MulHom.{u1, u2} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u1, succ u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f)) (a0 : G) (b0 : G) {A : Finset.{u2} H} {B : Finset.{u2} H}, (UniqueMul.{u2} H _inst_2 A B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f a0) (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f b0)) -> (UniqueMul.{u1} G _inst_1 (Finset.preimage.{u1, u2} G H A (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) A)))) (Finset.preimage.{u1, u2} G H B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) B)))) a0 b0)
-but is expected to have type
- forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
+<too large>
Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimageₓ'. -/
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` is preserved by inverse images under injective, additive maps."]
mathlib commit https://github.com/leanprover-community/mathlib/commit/95a87616d63b3cb49d3fe678d416fbe9c4217bf4
@@ -126,7 +126,7 @@ theorem exists_iff_exists_existsUnique :
lean 3 declaration is
forall {G : Type.{u1}} {H : Type.{u2}} [_inst_1 : Mul.{u1} G] [_inst_2 : Mul.{u2} H] (f : MulHom.{u1, u2} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u1, succ u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f)) (a0 : G) (b0 : G) {A : Finset.{u2} H} {B : Finset.{u2} H}, (UniqueMul.{u2} H _inst_2 A B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f a0) (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f b0)) -> (UniqueMul.{u1} G _inst_1 (Finset.preimage.{u1, u2} G H A (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) A)))) (Finset.preimage.{u1, u2} G H B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) B)))) a0 b0)
but is expected to have type
- forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
+ forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2397 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimageₓ'. -/
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` is preserved by inverse images under injective, additive maps."]
mathlib commit https://github.com/leanprover-community/mathlib/commit/0b9eaaa7686280fad8cce467f5c3c57ee6ce77f8
@@ -233,7 +233,12 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M)
end Additive
-#print eq_and_eq_of_le_of_le_of_mul_le /-
+/- warning: eq_and_eq_of_le_of_le_of_mul_le -> eq_and_eq_of_le_of_le_of_mul_le is a dubious translation:
+lean 3 declaration is
+ forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1))) (LT.lt.{u1} A (Preorder.toHasLt.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_5 : ContravariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] {a : A} {b : A} {a0 : A} {b0 : A}, (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) a0 a) -> (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) b0 b) -> (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a b) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a0 b0)) -> (And (Eq.{succ u1} A a a0) (Eq.{succ u1} A b b0))
+but is expected to have type
+ forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1830 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1832 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1830 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1832) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1845 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1847 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1845 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1847)] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1867 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1869 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1867 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1869)) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1882 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1884 : A) => LT.lt.{u1} A (Preorder.toLT.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1882 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1884)] [_inst_5 : ContravariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1901 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1903 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1901 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1903) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1916 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1918 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1916 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.1918)] {a : A} {b : A} {a0 : A} {b0 : A}, (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) a0 a) -> (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) b0 b) -> (LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a b) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) a0 b0)) -> (And (Eq.{succ u1} A a a0) (Eq.{succ u1} A b b0))
+Case conversion may be inaccurate. Consider using '#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_leₓ'. -/
@[to_additive]
theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
@@ -247,9 +252,13 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
--/
-#print Covariants.to_uniqueProds /-
+/- warning: covariants.to_unique_prods -> Covariants.to_uniqueProds is a dubious translation:
+lean 3 declaration is
+ forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1))) (LT.lt.{u1} A (Preorder.toHasLt.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))] [_inst_5 : ContravariantClass.{u1, u1} A A (HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1)) (LE.le.{u1} A (Preorder.toHasLe.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (LinearOrder.toLattice.{u1} A _inst_2))))))], UniqueProds.{u1} A _inst_1
+but is expected to have type
+ forall {A : Type.{u1}} [_inst_1 : Mul.{u1} A] [_inst_2 : LinearOrder.{u1} A] [_inst_3 : CovariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2108 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2110 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2108 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2110) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2123 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2125 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2123 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2125)] [_inst_4 : CovariantClass.{u1, u1} A A (Function.swap.{succ u1, succ u1, succ u1} A A (fun (ᾰ : A) (ᾰ : A) => A) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2145 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2147 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2145 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2147)) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2160 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2162 : A) => LT.lt.{u1} A (Preorder.toLT.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2160 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2162)] [_inst_5 : ContravariantClass.{u1, u1} A A (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2179 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2181 : A) => HMul.hMul.{u1, u1, u1} A A A (instHMul.{u1} A _inst_1) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2179 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2181) (fun (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2194 : A) (x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2196 : A) => LE.le.{u1} A (Preorder.toLE.{u1} A (PartialOrder.toPreorder.{u1} A (SemilatticeInf.toPartialOrder.{u1} A (Lattice.toSemilatticeInf.{u1} A (DistribLattice.toLattice.{u1} A (instDistribLattice.{u1} A _inst_2)))))) x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2194 x._@.Mathlib.Algebra.Group.UniqueProds._hyg.2196)], UniqueProds.{u1} A _inst_1
+Case conversion may be inaccurate. Consider using '#align covariants.to_unique_prods Covariants.to_uniqueProdsₓ'. -/
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `unique_prods`. -/
@@ -263,5 +272,4 @@ instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
eq_and_eq_of_le_of_le_of_mul_le (Finset.min'_le _ _ ‹_›) (Finset.min'_le _ _ ‹_›) ab.le⟩
#align covariants.to_unique_prods Covariants.to_uniqueProds
#align covariants.to_unique_sums Covariants.to_uniqueSums
--/
mathlib commit https://github.com/leanprover-community/mathlib/commit/3180fab693e2cee3bff62675571264cb8778b212
@@ -126,7 +126,7 @@ theorem exists_iff_exists_existsUnique :
lean 3 declaration is
forall {G : Type.{u1}} {H : Type.{u2}} [_inst_1 : Mul.{u1} G] [_inst_2 : Mul.{u2} H] (f : MulHom.{u1, u2} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u1, succ u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f)) (a0 : G) (b0 : G) {A : Finset.{u2} H} {B : Finset.{u2} H}, (UniqueMul.{u2} H _inst_2 A B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f a0) (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f b0)) -> (UniqueMul.{u1} G _inst_1 (Finset.preimage.{u1, u2} G H A (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) A)))) (Finset.preimage.{u1, u2} G H B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) B)))) a0 b0)
but is expected to have type
- forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
+ forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimageₓ'. -/
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` is preserved by inverse images under injective, additive maps."]
mathlib commit https://github.com/leanprover-community/mathlib/commit/38f16f960f5006c6c0c2bac7b0aba5273188f4e5
@@ -126,7 +126,7 @@ theorem exists_iff_exists_existsUnique :
lean 3 declaration is
forall {G : Type.{u1}} {H : Type.{u2}} [_inst_1 : Mul.{u1} G] [_inst_2 : Mul.{u2} H] (f : MulHom.{u1, u2} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u1, succ u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f)) (a0 : G) (b0 : G) {A : Finset.{u2} H} {B : Finset.{u2} H}, (UniqueMul.{u2} H _inst_2 A B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f a0) (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f b0)) -> (UniqueMul.{u1} G _inst_1 (Finset.preimage.{u1, u2} G H A (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) A)))) (Finset.preimage.{u1, u2} G H B (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) (Set.injOn_of_injective.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) hf (Set.preimage.{u1, u2} G H (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MulHom.{u1, u2} G H _inst_1 _inst_2) (fun (_x : MulHom.{u1, u2} G H _inst_1 _inst_2) => G -> H) (MulHom.hasCoeToFun.{u1, u2} G H _inst_1 _inst_2) f) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} H) (Set.{u2} H) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} H) (Set.{u2} H) (Finset.Set.hasCoeT.{u2} H))) B)))) a0 b0)
but is expected to have type
- forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2398 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
+ forall {G : Type.{u2}} {H : Type.{u1}} [_inst_1 : Mul.{u2} G] [_inst_2 : Mul.{u1} H] (f : MulHom.{u2, u1} G H _inst_1 _inst_2) (hf : Function.Injective.{succ u2, succ u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f)) (a0 : G) (b0 : G) {A : Finset.{u1} H} {B : Finset.{u1} H}, (UniqueMul.{u1} H _inst_2 A B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f a0) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f b0)) -> (UniqueMul.{u2} G _inst_1 (Finset.preimage.{u2, u1} G H A (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H A)))) (Finset.preimage.{u2, u1} G H B (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Set.injOn_of_injective.{u1, u2} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) hf (Set.preimage.{u2, u1} G H (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G (fun (_x : G) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2372 : G) => H) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MulHom.{u2, u1} G H _inst_1 _inst_2) G H _inst_1 _inst_2 (MulHom.mulHomClass.{u2, u1} G H _inst_1 _inst_2)) f) (Finset.toSet.{u1} H B)))) a0 b0)
Case conversion may be inaccurate. Consider using '#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimageₓ'. -/
/-- `unique_mul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`unique_add` is preserved by inverse images under injective, additive maps."]
mathlib commit https://github.com/leanprover-community/mathlib/commit/4c586d291f189eecb9d00581aeb3dd998ac34442
@@ -89,7 +89,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
#align unique_add.set_subsingleton UniqueAdd.set_subsingleton
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.iff_existsUnique /-
@[to_additive]
@@ -105,7 +105,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
#align unique_add.iff_exists_unique UniqueAdd.iff_existsUnique
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
#print UniqueMul.exists_iff_exists_existsUnique /-
@[to_additive]
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
@@ -444,7 +444,7 @@ open MulOpposite in
all_goals apply_rules [Nonempty.mul, Nonempty.image, Finset.Nonempty.map, hc.1, hc.2.1]
open UniqueMul in
-@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
+@[to_additive] instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
UniqueProds (∀ i, G i) where
uniqueMul_of_nonempty {A} := by
classical
@@ -472,7 +472,7 @@ open ULift in
have : ∀ b, UniqueProds (I G H b) := Bool.rec ?_ ?_
· exact of_injective_mulHom (downMulHom H) down_injective ‹_›
· refine of_injective_mulHom (Prod.upMulHom G H) (fun x y he => Prod.ext ?_ ?_)
- (instUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
+ (UniqueProds.instForall <| I G H) <;> apply up_injective
exacts [congr_fun he false, congr_fun he true]
· exact of_injective_mulHom (downMulHom G) down_injective ‹_›
@@ -521,7 +521,8 @@ theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f)
theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H :=
⟨of_injective_mulHom f.symm f.symm.injective, of_injective_mulHom f f.injective⟩
-@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
+@[to_additive]
+instance instForall {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
TwoUniqueProds (∀ i, G i) where
uniqueMul_of_one_lt_card {A} := by
classical
@@ -561,7 +562,7 @@ open ULift in
have : ∀ b, TwoUniqueProds (I G H b) := Bool.rec ?_ ?_
· exact of_injective_mulHom (downMulHom H) down_injective ‹_›
· refine of_injective_mulHom (Prod.upMulHom G H) (fun x y he ↦ Prod.ext ?_ ?_)
- (instTwoUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
+ (TwoUniqueProds.instForall <| I G H) <;> apply up_injective
exacts [congr_fun he false, congr_fun he true]
· exact of_injective_mulHom (downMulHom G) down_injective ‹_›
@@ -123,7 +123,9 @@ theorem iff_card_le_one [DecidableEq G] (ha0 : a0 ∈ A) (hb0 : b0 ∈ B) :
simp_rw [card_le_one_iff, mem_filter, mem_product]
refine ⟨fun h p1 p2 ⟨⟨ha1, hb1⟩, he1⟩ ⟨⟨ha2, hb2⟩, he2⟩ ↦ ?_, fun h a b ha hb he ↦ ?_⟩
· have h1 := h ha1 hb1 he1; have h2 := h ha2 hb2 he2
- ext; rw [h1.1, h2.1]; rw [h1.2, h2.2]
+ ext
+ · rw [h1.1, h2.1]
+ · rw [h1.2, h2.2]
· exact Prod.ext_iff.1 (@h (a, b) (a0, b0) ⟨⟨ha, hb⟩, he⟩ ⟨⟨ha0, hb0⟩, rfl⟩)
-- Porting note: mathport warning: expanding binder collection
@@ -407,8 +409,8 @@ open MulOpposite in
obtain ⟨a0, ha0, rfl⟩ := mem_map.mp hc
obtain ⟨b0, hb0, rfl⟩ := mem_map.mp hd
refine ⟨(_, _), ⟨ha0, hb0⟩, (a, b), ⟨ha, hb⟩, ?_, fun a' b' ha' hb' he => ?_, hu⟩
- simp_rw [Function.Embedding.coeFn_mk, Ne, inv_mul_eq_one, mul_inv_eq_one] at hne
- · rwa [Ne, Prod.mk.inj_iff, not_and_or, eq_comm]
+ · simp_rw [Function.Embedding.coeFn_mk, Ne, inv_mul_eq_one, mul_inv_eq_one] at hne
+ rwa [Ne, Prod.mk.inj_iff, not_and_or, eq_comm]
specialize hu' (mem_map_of_mem _ ha') (mem_map_of_mem _ hb')
simp_rw [Function.Embedding.coeFn_mk, mul_left_cancel_iff, mul_right_cancel_iff] at hu'
rw [mul_assoc, ← mul_assoc a', he, mul_assoc, mul_assoc] at hu'
@@ -458,8 +460,10 @@ open UniqueMul in
let A' := A.filter (· i = ai); let B' := B.filter (· i = bi)
obtain ⟨a0, ha0, b0, hb0, hu⟩ : ∃ a0 ∈ A', ∃ b0 ∈ B', UniqueMul A' B' a0 b0
· rcases hc with hc | hc; · exact ihA A' (hc.2 ai) hA hB
- by_cases hA' : A' = A; rw [hA']
- exacts [ihB B' (hc.2 bi) hB, ihA A' ((A.filter_subset _).ssubset_of_ne hA') hA hB]
+ by_cases hA' : A' = A
+ · rw [hA']
+ exact ihB B' (hc.2 bi) hB
+ · exact ihA A' ((A.filter_subset _).ssubset_of_ne hA') hA hB
rw [mem_filter] at ha0 hb0
exact ⟨a0, ha0.1, b0, hb0.1, of_image_filter (Pi.evalMulHom G i) ha0.2 hb0.2 hi hu⟩
@@ -531,7 +535,7 @@ theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔
⟨card_pos.2 (hA.image _), card_pos.2 (hB.image _), hc.imp And.left And.left⟩)
simp_rw [mem_product, mem_image, ← filter_nonempty_iff] at h1 h2
replace h1 := uniqueMul_of_twoUniqueMul ?_ h1.1 h1.2
- replace h2 := uniqueMul_of_twoUniqueMul ?_ h2.1 h2.2
+ on_goal 1 => replace h2 := uniqueMul_of_twoUniqueMul ?_ h2.1 h2.2
· obtain ⟨a1, ha1, b1, hb1, hu1⟩ := h1
obtain ⟨a2, ha2, b2, hb2, hu2⟩ := h2
@@ -543,10 +547,14 @@ theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔
contrapose! hne; rw [Prod.mk.inj_iff] at hne ⊢
rw [← ha1.2, ← hb1.2, ← ha2.2, ← hb2.2, hne.1, hne.2]; exact ⟨rfl, rfl⟩
all_goals rcases hc with hc | hc; · exact ihA _ (hc.2 _)
- · by_cases hA : A.filter (· i = p2.1) = A; rw [hA]
- exacts [ihB _ (hc.2 _), ihA _ ((A.filter_subset _).ssubset_of_ne hA)]
- · by_cases hA : A.filter (· i = p1.1) = A; rw [hA]
- exacts [ihB _ (hc.2 _), ihA _ ((A.filter_subset _).ssubset_of_ne hA)]
+ · by_cases hA : A.filter (· i = p2.1) = A
+ · rw [hA]
+ exact ihB _ (hc.2 _)
+ · exact ihA _ ((A.filter_subset _).ssubset_of_ne hA)
+ · by_cases hA : A.filter (· i = p1.1) = A
+ · rw [hA]
+ exact ihB _ (hc.2 _)
+ · exact ihA _ ((A.filter_subset _).ssubset_of_ne hA)
open ULift in
@[to_additive] instance [TwoUniqueProds G] [TwoUniqueProds H] : TwoUniqueProds (G × H) := by
@@ -310,7 +310,6 @@ variable (G : Type u) (H : Type v) [Mul G] [Mul H]
private abbrev I : Bool → Type max u v := Bool.rec (ULift.{v} G) (ULift.{u} H)
@[to_additive] private instance : ∀ b, Mul (I G H b) := Bool.rec ULift.mul ULift.mul
-@[to_additive] private instance : Mul (∀ b, I G H b) := inferInstance
@[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 (_|_) <;> rfl⟩
@[to_additive] private def downMulHom : ULift G →ₙ* G := ⟨ULift.down, fun _ _ ↦ rfl⟩
This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0
branch as we update to intermediate nightlies.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>
@@ -399,7 +399,7 @@ open MulOpposite in
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⁻¹
- have hcard : 1 < C.card ∨ 1 < D.card := by simp_rw [card_map]; exact hc.2.2
+ have hcard : 1 < C.card ∨ 1 < D.card := by simp_rw [C, D, card_map]; exact hc.2.2
have hC : 1 ∈ C := mem_map.mpr ⟨a, ha, inv_mul_self a⟩
have hD : 1 ∈ D := mem_map.mpr ⟨b, hb, mul_inv_self b⟩
suffices ∃ c ∈ C, ∃ d ∈ D, (c ≠ 1 ∨ d ≠ 1) ∧ UniqueMul C D c d by
have
, replace
and suffices
(#10640)
No changes to tactic file, it's just boring fixes throughout the library.
This follows on from #6964.
Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -399,11 +399,11 @@ open MulOpposite in
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⁻¹
- have hcard : 1 < C.card ∨ 1 < D.card; · simp_rw [card_map]; exact hc.2.2
+ have hcard : 1 < C.card ∨ 1 < D.card := by simp_rw [card_map]; exact hc.2.2
have hC : 1 ∈ C := mem_map.mpr ⟨a, ha, inv_mul_self a⟩
have hD : 1 ∈ D := mem_map.mpr ⟨b, hb, mul_inv_self b⟩
- suffices : ∃ c ∈ C, ∃ d ∈ D, (c ≠ 1 ∨ d ≠ 1) ∧ UniqueMul C D c d
- · simp_rw [mem_product]
+ suffices ∃ c ∈ C, ∃ d ∈ D, (c ≠ 1 ∨ d ≠ 1) ∧ UniqueMul C D c d by
+ simp_rw [mem_product]
obtain ⟨c, hc, d, hd, hne, hu'⟩ := this
obtain ⟨a0, ha0, rfl⟩ := mem_map.mp hc
obtain ⟨b0, hb0, rfl⟩ := mem_map.mp hd
@@ -591,8 +591,8 @@ instance (priority := 100) of_covariant_right [IsRightCancelMul G]
rw [← card_product] at hc
obtain ⟨a0, ha0, b0, hb0, he0⟩ := mem_mul.mp (max'_mem _ <| hA.mul hB)
obtain ⟨a1, ha1, b1, hb1, he1⟩ := mem_mul.mp (min'_mem _ <| hA.mul hB)
- have : UniqueMul A B a0 b0
- · intro a b ha hb he
+ have : UniqueMul A B a0 b0 := by
+ intro a b ha hb he
obtain hl | rfl | hl := lt_trichotomy b b0
· exact ((he0 ▸ he ▸ mul_lt_mul_left' hl a).not_le <| le_max' _ _ <| mul_mem_mul ha hb0).elim
· exact ⟨mul_right_cancel he, rfl⟩
@@ -533,6 +533,7 @@ theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔
simp_rw [mem_product, mem_image, ← filter_nonempty_iff] at h1 h2
replace h1 := uniqueMul_of_twoUniqueMul ?_ h1.1 h1.2
replace h2 := uniqueMul_of_twoUniqueMul ?_ h2.1 h2.2
+
· obtain ⟨a1, ha1, b1, hb1, hu1⟩ := h1
obtain ⟨a2, ha2, b2, hb2, hu2⟩ := h2
rw [mem_filter] at ha1 hb1 ha2 hb2
@@ -542,9 +543,10 @@ theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔
UniqueMul.of_image_filter (Pi.evalMulHom G i) ha2.2 hb2.2 hi2 hu2⟩
contrapose! hne; rw [Prod.mk.inj_iff] at hne ⊢
rw [← ha1.2, ← hb1.2, ← ha2.2, ← hb2.2, hne.1, hne.2]; exact ⟨rfl, rfl⟩
- all_goals
- rcases hc with hc | hc; · exact ihA _ (hc.2 _)
- by_cases hA : A.filter (· i = _) = A; rw [hA]
+ all_goals rcases hc with hc | hc; · exact ihA _ (hc.2 _)
+ · by_cases hA : A.filter (· i = p2.1) = A; rw [hA]
+ exacts [ihB _ (hc.2 _), ihA _ ((A.filter_subset _).ssubset_of_ne hA)]
+ · by_cases hA : A.filter (· i = p1.1) = A; rw [hA]
exacts [ihB _ (hc.2 _), ihA _ ((A.filter_subset _).ssubset_of_ne hA)]
open ULift in
The FunLike hierarchy is very big and gets scanned through each time we need a coercion (via the CoeFun
instance). It looks like unbundled inheritance suits Lean 4 better here. The only class that still extends FunLike
is EquivLike
, since that has a custom coe_injective'
field that is easier to implement. All other classes should take FunLike
or EquivLike
as a parameter.
Previously, morphism classes would be Type
-valued and extend FunLike
:
/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
extends FunLike F A B :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))
After this PR, they should be Prop
-valued and take FunLike
as a parameter:
/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
[FunLike F A B] : Prop :=
(map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))
(Note that A B
stay marked as outParam
even though they are not purely required to be so due to the FunLike
parameter already filling them in. This is required to see through type synonyms, which is important in the category theory library. Also, I think keeping them as outParam
is slightly faster.)
Similarly, MyEquivClass
should take EquivLike
as a parameter.
As a result, every mention of [MyHomClass F A B]
should become [FunLike F A B] [MyHomClass F A B]
.
While overall this gives some great speedups, there are some cases that are noticeably slower. In particular, a failing application of a lemma such as map_mul
is more expensive. This is due to suboptimal processing of arguments. For example:
variable [FunLike F M N] [Mul M] [Mul N] (f : F) (x : M) (y : M)
theorem map_mul [MulHomClass F M N] : f (x * y) = f x * f y
example [AddHomClass F A B] : f (x * y) = f x * f y := map_mul f _ _
Before this PR, applying map_mul f
gives the goals [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]
. Since M
and N
are out_param
s, [MulHomClass F ?M ?N]
is synthesized first, supplies values for ?M
and ?N
and then the Mul M
and Mul N
instances can be found.
After this PR, the goals become [FunLike F ?M ?N] [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]
. Now [FunLike F ?M ?N]
is synthesized first, supplies values for ?M
and ?N
and then the Mul M
and Mul N
instances can be found, before trying MulHomClass F M N
which fails. Since the Mul
hierarchy is very big, this can be slow to fail, especially when there is no such Mul
instance.
A long-term but harder to achieve solution would be to specify the order in which instance goals get solved. For example, we'd like to change the arguments to map_mul
to look like [FunLike F M N] [Mul M] [Mul N] [highPriority <| MulHomClass F M N]
because MulHomClass
fails or succeeds much faster than the others.
As a consequence, the simpNF
linter is much slower since by design it tries and fails to apply many map_
lemmas. The same issue occurs a few times in existing calls to simp [map_mul]
, where map_mul
is tried "too soon" and fails. Thanks to the speedup of leanprover/lean4#2478 the impact is very limited, only in files that already were close to the timeout.
simp
not firing sometimesThis affects map_smulₛₗ
and related definitions. For simp
lemmas Lean apparently uses a slightly different mechanism to find instances, so that rw
can find every argument to map_smulₛₗ
successfully but simp
can't: leanprover/lean4#3701.
Especially in the category theory library, we might sometimes have a type A
which is also accessible as a synonym (Bundled A hA).1
. Instance synthesis doesn't always work if we have f : A →* B
but x * y : (Bundled A hA).1
or vice versa. This seems to be mostly fixed by keeping A B
as outParam
s in MulHomClass F A B
. (Presumably because Lean will do a definitional check A =?= (Bundled A hA).1
instead of using the syntax in the discrimination tree.)
The timeouts can be worked around for now by specifying which map_mul
we mean, either as map_mul f
for some explicit f
, or as e.g. MonoidHomClass.map_mul
.
map_smulₛₗ
not firing as simp
lemma can be worked around by going back to the pre-FunLike situation and making LinearMap.map_smulₛₗ
a simp
lemma instead of the generic map_smulₛₗ
. Writing simp [map_smulₛₗ _]
also works.
Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott@tqft.net> Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
@@ -652,7 +652,7 @@ instance [AddCommGroup G] [Module ℚ G] : TwoUniqueSums G :=
/-- Any `FreeMonoid` has the `TwoUniqueProds` property. -/
instance FreeMonoid.instTwoUniqueProds {κ : Type*} : TwoUniqueProds (FreeMonoid κ) :=
.of_mulHom ⟨Multiplicative.ofAdd ∘ List.length, fun _ _ ↦ congr_arg _ (List.length_append _ _)⟩
- (fun _ _ _ _ h h' ↦ List.append_inj h <| Equiv.injective _ h'.1)
+ (fun _ _ _ _ h h' ↦ List.append_inj h <| Equiv.injective Multiplicative.ofAdd h'.1)
/-- Any `FreeAddMonoid` has the `TwoUniqueSums` property. -/
instance FreeAddMonoid.instTwoUniqueSums {κ : Type*} : TwoUniqueSums (FreeAddMonoid κ) :=
Provide instances
Nontrivial (TensorAlgebra R M)
when M
is a module over
a nontrivial semiring R
NoZeroDivisors (FreeAlgebra R X)
when R
is a commutative
semiring with no zero-divisors and X
any typeIsDomain (FreeAlgebra R X)
when R
is an integral domain
and X
is any typeTwoUniqueProds (FreeMonoid X)
where X
is any type
(this provides NoZeroDivisors (MonoidAlgebra R (FreeMonoid X))
when R
is a semiring and X
any type,
via TwoUniqueProds.toUniqueProds
and MonoidAlgebra.instNoZeroDivisorsOfUniqueProds
)NoZeroDivisors (TensorAlgebra R M)
when M
is a free module
over a commutative semiring R
with no zero-divisorsIsDomain (TensorAlgebra R M)
when M
is a free module over
an integral domain R
In Algebra.Group.UniqueProds:
UniqueProds.mulHom_image_of_injective
to
UniqueProds.of_injective_mulHom
.UniqueMul.of_mulHom_image
, UniqueProds.of_mulHom
,
TwoUniqueProds.of_mulHom
show the relevant property holds in the
domain of a multiplicative homomorphism if it holds in the codomain,
under a certain hypothesis on the homomorphism.Co-authored-by: Richard Copley <rcopley@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -152,6 +152,12 @@ theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G
#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimage
#align unique_add.add_hom_preimage UniqueAdd.addHom_preimage
+@[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 :=
+ fun a b ha hb ab ↦ hf ab
+ (h (Finset.mem_image_of_mem f ha) (Finset.mem_image_of_mem f hb) <| by simp_rw [← map_mul, ab])
+
/-- `Unique_Mul` is preserved under multiplicative maps that are injective.
See `UniqueMul.mulHom_map_iff` for a version with swapped bundling. -/
@@ -160,15 +166,12 @@ See `UniqueMul.mulHom_map_iff` for a version with swapped bundling. -/
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 := by
- simp_rw [UniqueMul, Finset.mem_image]
- refine ⟨fun h a b ha hb ab ↦ ?_, fun h _ _ ↦ ?_⟩
- · rw [← hf.eq_iff, map_mul, map_mul] at ab
- have := h ⟨a, ha, rfl⟩ ⟨b, hb, rfl⟩ ab
- exact ⟨hf this.1, hf this.2⟩
- · rintro ⟨a, aA, rfl⟩ ⟨b, bB, rfl⟩ ab
- simp only [← map_mul, hf.eq_iff] at ab ⊢
- exact h aA bB ab
+ UniqueMul (A.image f) (B.image f) (f a0) (f b0) ↔ UniqueMul A B a0 b0 :=
+ ⟨of_mulHom_image f fun _ _ _ _ _ ↦ .imp (hf ·) (hf ·), fun h _ _ ↦ by
+ simp_rw [Finset.mem_image]
+ rintro ⟨a, aA, rfl⟩ ⟨b, bB, rfl⟩ ab
+ simp_rw [← map_mul, hf.eq_iff] at ab ⊢
+ exact h aA bB ab⟩
#align unique_mul.mul_hom_image_iff UniqueMul.mulHom_image_iff
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
@@ -318,21 +321,24 @@ namespace UniqueProds
open Finset
-@[to_additive]
-theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
- UniqueProds H where
+@[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 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⟩
- exact ⟨a', ha', b', hb', (UniqueMul.mulHom_image_iff f hf).mp h⟩
+ obtain ⟨a0, ha0, b0, hb0, h⟩ := uniqueMul_of_nonempty (A0.image f) (B0.image f)
+ obtain ⟨a', ha', rfl⟩ := mem_image.mp ha0
+ obtain ⟨b', hb', rfl⟩ := mem_image.mp hb0
+ exact ⟨a', ha', b', hb', UniqueMul.of_mulHom_image f hf h⟩
+
+@[to_additive]
+theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f) (_ : UniqueProds G) :
+ UniqueProds H := of_mulHom f (fun _ _ _ _ _ ↦ .imp (hf ·) (hf ·))
/-- `UniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`UniqueSums` is preserved under additive equivalences."]
-theorem mulHom_image_iff (f : G ≃* H) :
- UniqueProds G ↔ UniqueProds H :=
- ⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+theorem _root_.MulEquiv.uniqueProds_iff (f : G ≃* H) : UniqueProds G ↔ UniqueProds H :=
+ ⟨of_injective_mulHom f.symm f.symm.injective, of_injective_mulHom f f.injective⟩
open Finset MulOpposite in
@[to_additive]
@@ -343,7 +349,7 @@ theorem of_mulOpposite (h : UniqueProds Gᵐᵒᵖ) : UniqueProds G where
⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩
@[to_additive] instance [h : UniqueProds G] : UniqueProds Gᵐᵒᵖ :=
- of_mulOpposite <| (mulHom_image_iff <| MulEquiv.opOp G).mp h
+ of_mulOpposite <| (MulEquiv.opOp G).uniqueProds_iff.mp h
@[to_additive] private theorem toIsLeftCancelMul [UniqueProds G] : IsLeftCancelMul G where
mul_left_cancel a b1 b2 he := by
@@ -461,46 +467,56 @@ open UniqueMul in
open ULift in
@[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) := by
have : ∀ b, UniqueProds (I G H b) := Bool.rec ?_ ?_
- · exact mulHom_image_of_injective (downMulHom H) down_injective ‹_›
- · refine mulHom_image_of_injective (Prod.upMulHom G H) (fun x y he => Prod.ext ?_ ?_)
+ · exact of_injective_mulHom (downMulHom H) down_injective ‹_›
+ · refine of_injective_mulHom (Prod.upMulHom G H) (fun x y he => Prod.ext ?_ ?_)
(instUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
exacts [congr_fun he false, congr_fun he true]
- · exact mulHom_image_of_injective (downMulHom G) down_injective ‹_›
+ · exact of_injective_mulHom (downMulHom G) down_injective ‹_›
end UniqueProds
instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums (G i)] :
UniqueSums (Π₀ i, G i) :=
- UniqueSums.addHom_image_of_injective
+ UniqueSums.of_injective_addHom
DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance
instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) :=
- UniqueSums.addHom_image_of_injective
+ UniqueSums.of_injective_addHom
Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance
namespace TwoUniqueProds
open Finset
-@[to_additive]
-theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f)
- (uG : TwoUniqueProds G) : TwoUniqueProds H where
+@[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 where
uniqueMul_of_one_lt_card {A B} hc := by
classical
- simp_rw [← card_map ⟨f, hf⟩] at hc
- obtain ⟨⟨a1, b1⟩, h1, ⟨a2, b2⟩, h2, hne, hu1, hu2⟩ := uG.uniqueMul_of_one_lt_card hc
- simp only [mem_product, mem_map] at h1 h2 ⊢
- obtain ⟨⟨a1, ha1, rfl⟩, ⟨b1, hb1, rfl⟩⟩ := h1
- obtain ⟨⟨a2, ha2, rfl⟩, ⟨b2, hb2, rfl⟩⟩ := h2
- refine ⟨(a1, b1), ⟨ha1, hb1⟩, (a2, b2), ⟨ha2, hb2⟩, ?_, ?_, ?_⟩
- · rw [Ne, Prod.ext_iff] at hne ⊢; simp_rw [← hf.eq_iff]; exact hne
- all_goals apply (UniqueMul.mulHom_map_iff ⟨f, hf⟩ f.2).mp
- exacts [hu1, hu2]
+ obtain hc' | hc' := lt_or_le 1 ((A.image f).card * (B.image f).card)
+ · obtain ⟨⟨a1, b1⟩, h1, ⟨a2, b2⟩, h2, hne, hu1, hu2⟩ := uniqueMul_of_one_lt_card hc'
+ simp_rw [mem_product, mem_image] at h1 h2 ⊢
+ obtain ⟨⟨a1, ha1, rfl⟩, b1, hb1, rfl⟩ := h1
+ obtain ⟨⟨a2, ha2, rfl⟩, b2, hb2, rfl⟩ := h2
+ exact ⟨(a1, b1), ⟨ha1, hb1⟩, (a2, b2), ⟨ha2, hb2⟩, mt (congr_arg (Prod.map f f)) hne,
+ UniqueMul.of_mulHom_image f hf hu1, UniqueMul.of_mulHom_image f hf hu2⟩
+ rw [← card_product] at hc hc'
+ obtain ⟨p1, h1, p2, h2, hne⟩ := one_lt_card_iff_nontrivial.mp hc
+ refine ⟨p1, h1, p2, h2, hne, ?_⟩
+ cases mem_product.mp h1; cases mem_product.mp h2
+ constructor <;> refine UniqueMul.of_mulHom_image f hf
+ ((UniqueMul.iff_card_le_one ?_ ?_).mpr <| (card_filter_le _ _).trans hc') <;>
+ apply mem_image_of_mem <;> assumption
+
+@[to_additive]
+theorem of_injective_mulHom (f : H →ₙ* G) (hf : Function.Injective f)
+ (_ : TwoUniqueProds G) : TwoUniqueProds H :=
+ of_mulHom f (fun _ _ _ _ _ ↦ .imp (hf ·) (hf ·))
/-- `TwoUniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`TwoUniqueSums` is preserved under additive equivalences."]
-theorem mulHom_image_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H :=
- ⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+theorem _root_.MulEquiv.twoUniqueProds_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H :=
+ ⟨of_injective_mulHom f.symm f.symm.injective, of_injective_mulHom f f.injective⟩
@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
TwoUniqueProds (∀ i, G i) where
@@ -534,11 +550,11 @@ theorem mulHom_image_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H
open ULift in
@[to_additive] instance [TwoUniqueProds G] [TwoUniqueProds H] : TwoUniqueProds (G × H) := by
have : ∀ b, TwoUniqueProds (I G H b) := Bool.rec ?_ ?_
- · exact mulHom_image_of_injective (downMulHom H) down_injective ‹_›
- · refine mulHom_image_of_injective (Prod.upMulHom G H) (fun x y he ↦ Prod.ext ?_ ?_)
+ · exact of_injective_mulHom (downMulHom H) down_injective ‹_›
+ · refine of_injective_mulHom (Prod.upMulHom G H) (fun x y he ↦ Prod.ext ?_ ?_)
(instTwoUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
exacts [congr_fun he false, congr_fun he true]
- · exact mulHom_image_of_injective (downMulHom G) down_injective ‹_›
+ · exact of_injective_mulHom (downMulHom G) down_injective ‹_›
open MulOpposite in
@[to_additive]
@@ -556,7 +572,7 @@ theorem of_mulOpposite (h : TwoUniqueProds Gᵐᵒᵖ) : TwoUniqueProds G where
exacts [h1.2, h1.1, h2.2, h2.1]
@[to_additive] instance [h : TwoUniqueProds G] : TwoUniqueProds Gᵐᵒᵖ :=
- of_mulOpposite <| (mulHom_image_iff <| MulEquiv.opOp G).mp h
+ of_mulOpposite <| (MulEquiv.opOp G).twoUniqueProds_iff.mp h
-- see Note [lower instance priority]
/-- This instance asserts that if `G` has a right-cancellative multiplication, a linear order, and
@@ -608,17 +624,36 @@ instance (priority := 100) of_covariant_left [IsLeftCancelMul G]
end TwoUniqueProds
+-- deprecated 2024-02-04
+@[deprecated] alias UniqueProds.mulHom_image_of_injective := UniqueProds.of_injective_mulHom
+@[deprecated] alias UniqueSums.addHom_image_of_injective := UniqueSums.of_injective_addHom
+@[deprecated] alias UniqueProds.mulHom_image_iff := MulEquiv.uniqueProds_iff
+@[deprecated] alias UniqueSums.addHom_image_iff := AddEquiv.uniqueSums_iff
+@[deprecated] alias TwoUniqueProds.mulHom_image_of_injective := TwoUniqueProds.of_injective_mulHom
+@[deprecated] alias TwoUniqueSums.addHom_image_of_injective := TwoUniqueSums.of_injective_addHom
+@[deprecated] alias TwoUniqueProds.mulHom_image_iff := MulEquiv.twoUniqueProds_iff
+@[deprecated] alias TwoUniqueSums.addHom_image_iff := AddEquiv.twoUniqueSums_iff
+
instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] :
TwoUniqueSums (Π₀ i, G i) :=
- TwoUniqueSums.addHom_image_of_injective
+ TwoUniqueSums.of_injective_addHom
DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance
instance {ι G} [AddZeroClass G] [TwoUniqueSums G] : TwoUniqueSums (ι →₀ G) :=
- TwoUniqueSums.addHom_image_of_injective
+ TwoUniqueSums.of_injective_addHom
Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance
/-- 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 :=
- TwoUniqueSums.addHom_image_of_injective _ (Basis.ofVectorSpace ℚ G).repr.injective inferInstance
+ TwoUniqueSums.of_injective_addHom _ (Basis.ofVectorSpace ℚ G).repr.injective inferInstance
+
+/-- Any `FreeMonoid` has the `TwoUniqueProds` property. -/
+instance FreeMonoid.instTwoUniqueProds {κ : Type*} : TwoUniqueProds (FreeMonoid κ) :=
+ .of_mulHom ⟨Multiplicative.ofAdd ∘ List.length, fun _ _ ↦ congr_arg _ (List.length_append _ _)⟩
+ (fun _ _ _ _ h h' ↦ List.append_inj h <| Equiv.injective _ h'.1)
+
+/-- Any `FreeAddMonoid` has the `TwoUniqueSums` property. -/
+instance FreeAddMonoid.instTwoUniqueSums {κ : Type*} : TwoUniqueSums (FreeAddMonoid κ) :=
+ .of_addHom ⟨_, List.length_append⟩ (fun _ _ _ _ h h' ↦ List.append_inj h h'.1)
FunLike
to DFunLike
(#9785)
This prepares for the introduction of a non-dependent synonym of FunLike, which helps a lot with keeping #8386 readable.
This is entirely search-and-replace in 680197f combined with manual fixes in 4145626, e900597 and b8428f8. The commands that generated this change:
sed -i 's/\bFunLike\b/DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoFunLike\b/toDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/import Mathlib.Data.DFunLike/import Mathlib.Data.FunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bHom_FunLike\b/Hom_DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\binstFunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bfunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoo many metavariables to apply `fun_like.has_coe_to_fun`/too many metavariables to apply `DFunLike.hasCoeToFun`/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
@@ -472,11 +472,11 @@ end UniqueProds
instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums (G i)] :
UniqueSums (Π₀ i, G i) :=
UniqueSums.addHom_image_of_injective
- DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance
+ DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance
instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) :=
UniqueSums.addHom_image_of_injective
- Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance
+ Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance
namespace TwoUniqueProds
@@ -611,11 +611,11 @@ end TwoUniqueProds
instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] :
TwoUniqueSums (Π₀ i, G i) :=
TwoUniqueSums.addHom_image_of_injective
- DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance
+ DFinsupp.coeFnAddMonoidHom.toAddHom DFunLike.coe_injective inferInstance
instance {ι G} [AddZeroClass G] [TwoUniqueSums G] : TwoUniqueSums (ι →₀ G) :=
TwoUniqueSums.addHom_image_of_injective
- Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance
+ Finsupp.coeFnAddHom.toAddHom DFunLike.coe_injective inferInstance
/-- Any `ℚ`-vector space has `TwoUniqueSums`, because it is isomorphic to some
`(Basis.ofVectorSpaceIndex ℚ G) →₀ ℚ` by choosing a basis, and `ℚ` already has
Set.image2
etc (#9275)
Set.image2
to use ∃ a ∈ s, ∃ b ∈ t, f a b = c
instead of ∃ a b, a ∈ s ∧ b ∈ t ∧ f a b = c
.Set.seq
as Set.image2
. The new definition is equal to the old one but rw [Set.seq]
gives a different result.Filter.map₂
to use ∃ u ∈ f, ∃ v ∈ g, image2 m u v ⊆ s
instead of ∃ u v, u ∈ f ∧ v ∈ g ∧ ...
Set.mem_image2
, Finset.mem_image₂
, Set.mem_mul
, Finset.mem_div
etcThe two reasons to make the change are:
∃ a ∈ s, ∃ b ∈ t, _
is a simp
-normal form, and@@ -375,8 +375,8 @@ open MulOpposite in
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
+ obtain ⟨b1, hb1, a1, ha1, rfl⟩ := mem_mul.mp h1
+ obtain ⟨b2, hb2, a2, 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]
@@ -414,26 +414,26 @@ open MulOpposite in
· obtain ⟨e, he, f, hf, hu⟩ := this
clear_value C D
simp only [UniqueMul, mem_mul, mem_image] at he hf hu
- obtain ⟨_, c1, ⟨d1, hd1, rfl⟩, hc1, rfl⟩ := he
- obtain ⟨d2, _, hd2, ⟨c2, hc2, rfl⟩, rfl⟩ := hf
+ obtain ⟨_, ⟨d1, hd1, rfl⟩, c1, hc1, rfl⟩ := he
+ obtain ⟨d2, hd2, _, ⟨c2, hc2, rfl⟩, rfl⟩ := hf
by_cases h12 : c1 ≠ 1 ∨ d2 ≠ 1
· refine ⟨c1, hc1, d2, hd2, h12, fun c3 d3 hc3 hd3 he => ?_⟩
- specialize hu ⟨_, _, ⟨_, hd1, rfl⟩, hc3, rfl⟩ ⟨_, _, hd3, ⟨_, hc2, rfl⟩, rfl⟩
+ specialize hu ⟨_, ⟨_, hd1, rfl⟩, _, hc3, rfl⟩ ⟨_, hd3, _, ⟨_, hc2, rfl⟩, rfl⟩
rw [mul_left_cancel_iff, mul_right_cancel_iff,
mul_assoc, ← mul_assoc c3, he, mul_assoc, mul_assoc] at hu; exact hu rfl
push_neg at h12; obtain ⟨rfl, rfl⟩ := h12
by_cases h21 : c2 ≠ 1 ∨ d1 ≠ 1
· refine ⟨c2, hc2, d1, hd1, h21, fun c4 d4 hc4 hd4 he => ?_⟩
- specialize hu ⟨_, _, ⟨_, hd4, rfl⟩, hC, rfl⟩ ⟨_, _, hD, ⟨_, hc4, rfl⟩, rfl⟩
+ specialize hu ⟨_, ⟨_, hd4, rfl⟩, _, hC, rfl⟩ ⟨_, hD, _, ⟨_, hc4, rfl⟩, rfl⟩
simpa only [mul_one, one_mul, ← mul_inv_rev, he, true_imp_iff, inv_inj, and_comm] using hu
push_neg at h21; obtain ⟨rfl, rfl⟩ := h21
rcases hcard with hC | hD
· obtain ⟨c, hc, hc1⟩ := exists_ne_of_one_lt_card hC 1
refine (hc1 ?_).elim
- simpa using hu ⟨_, _, ⟨_, hD, rfl⟩, hc, rfl⟩ ⟨_, _, hD, ⟨_, hc, rfl⟩, rfl⟩
+ simpa using hu ⟨_, ⟨_, hD, rfl⟩, _, hc, rfl⟩ ⟨_, hD, _, ⟨_, hc, rfl⟩, rfl⟩
· obtain ⟨d, hd, hd1⟩ := exists_ne_of_one_lt_card hD 1
refine (hd1 ?_).elim
- simpa using hu ⟨_, _, ⟨_, hd, rfl⟩, hC, rfl⟩ ⟨_, _, hd, ⟨_, hC, rfl⟩, rfl⟩
+ simpa using hu ⟨_, ⟨_, hd, rfl⟩, _, hC, rfl⟩ ⟨_, hd, _, ⟨_, hC, rfl⟩, rfl⟩
all_goals apply_rules [Nonempty.mul, Nonempty.image, Finset.Nonempty.map, hc.1, hc.2.1]
open UniqueMul in
@@ -571,8 +571,8 @@ instance (priority := 100) of_covariant_right [IsRightCancelMul G]
obtain ⟨hA, hB, -⟩ := Nat.one_lt_mul_iff.mp hc
rw [card_pos] at hA hB
rw [← card_product] at hc
- obtain ⟨a0, b0, ha0, hb0, he0⟩ := mem_mul.mp (max'_mem _ <| hA.mul hB)
- obtain ⟨a1, b1, ha1, hb1, he1⟩ := mem_mul.mp (min'_mem _ <| hA.mul hB)
+ obtain ⟨a0, ha0, b0, hb0, he0⟩ := mem_mul.mp (max'_mem _ <| hA.mul hB)
+ obtain ⟨a1, ha1, b1, hb1, he1⟩ := mem_mul.mp (min'_mem _ <| hA.mul hB)
have : UniqueMul A B a0 b0
· intro a b ha hb he
obtain hl | rfl | hl := lt_trichotomy b b0
@@ -420,7 +420,7 @@ open MulOpposite in
· refine ⟨c1, hc1, d2, hd2, h12, fun c3 d3 hc3 hd3 he => ?_⟩
specialize hu ⟨_, _, ⟨_, hd1, rfl⟩, hc3, rfl⟩ ⟨_, _, hd3, ⟨_, hc2, rfl⟩, rfl⟩
rw [mul_left_cancel_iff, mul_right_cancel_iff,
- mul_assoc, ←mul_assoc c3, he, mul_assoc, mul_assoc] at hu; exact hu rfl
+ mul_assoc, ← mul_assoc c3, he, mul_assoc, mul_assoc] at hu; exact hu rfl
push_neg at h12; obtain ⟨rfl, rfl⟩ := h12
by_cases h21 : c2 ≠ 1 ∨ d1 ≠ 1
· refine ⟨c2, hc2, d1, hd1, h21, fun c4 d4 hc4 hd4 he => ?_⟩
@@ -203,7 +203,7 @@ theorem to_mulOpposite (h : UniqueMul A B a0 b0) :
theorem iff_mulOpposite :
UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) ↔
UniqueMul A B a0 b0 :=
-⟨of_mulOpposite, to_mulOpposite⟩
+ ⟨of_mulOpposite, to_mulOpposite⟩
end Opposites
@@ -332,7 +332,7 @@ theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f)
@[to_additive "`UniqueSums` is preserved under additive equivalences."]
theorem mulHom_image_iff (f : G ≃* H) :
UniqueProds G ↔ UniqueProds H :=
-⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+ ⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
open Finset MulOpposite in
@[to_additive]
@@ -500,7 +500,7 @@ theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f)
/-- `TwoUniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`TwoUniqueSums` is preserved under additive equivalences."]
theorem mulHom_image_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H :=
-⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+ ⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
TwoUniqueProds (∀ i, G i) where
@@ -564,7 +564,7 @@ theorem of_mulOpposite (h : TwoUniqueProds Gᵐᵒᵖ) : TwoUniqueProds G where
@[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]
+instance (priority := 100) of_covariant_right [IsRightCancelMul G]
[LinearOrder G] [CovariantClass G G (· * ·) (· < ·)] :
TwoUniqueProds G where
uniqueMul_of_one_lt_card {A B} hc := by
@@ -598,13 +598,13 @@ open MulOpposite in
@[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]
+instance (priority := 100) of_covariant_left [IsLeftCancelMul G]
[LinearOrder G] [CovariantClass G G (Function.swap (· * ·)) (· < ·)] :
TwoUniqueProds G :=
let _ := LinearOrder.lift' (unop : Gᵐᵒᵖ → G) unop_injective
let _ : CovariantClass Gᵐᵒᵖ Gᵐᵒᵖ (· * ·) (· < ·) :=
- { elim := fun _ _ _ bc ↦ mul_lt_mul_right' (α := G) bc (unop _) }
- of_mulOpposite of_Covariant_right
+ { elim := fun _ _ _ bc ↦ mul_lt_mul_right' (α := G) bc (unop _) }
+ of_mulOpposite of_covariant_right
end TwoUniqueProds
attribute [simp] ... in
-> attribute [local simp] ... in
(#7678)
Mathlib.Logic.Unique contains the line attribute [simp] eq_iff_true_of_subsingleton in ...
:
Despite what the in
part may imply, this adds the lemma to the simp set "globally", including for downstream files; it is likely that attribute [local simp] eq_iff_true_of_subsingleton in ...
was meant instead (or maybe scoped simp
, but I think "scoped" refers to the current namespace). Indeed, the relevant lemma is not marked with @[simp]
for possible slowness: https://github.com/leanprover/std4/blob/846e9e1d6bb534774d1acd2dc430e70987da3c18/Std/Logic.lean#L749. Adding it to the simp set causes the example at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Regression.20in.20simp to slow down.
This PR changes this and fixes the relevant downstream simp
s. There was also one ocurrence of attribute [simp] FullSubcategory.comp_def FullSubcategory.id_def in
in Mathlib.CategoryTheory.Monoidal.Subcategory but that was much easier to fix.
@@ -64,7 +64,8 @@ namespace UniqueMul
variable {G H : Type*} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
@[to_additive (attr := nontriviality, simp)]
-theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 := by simp [UniqueMul]
+theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 := by
+ simp [UniqueMul, eq_iff_true_of_subsingleton]
@[to_additive]
theorem of_card_le_one (hA : A.Nonempty) (hB : B.Nonempty) (hA1 : A.card ≤ 1) (hB1 : B.card ≤ 1) :
@@ -344,6 +344,97 @@ theorem of_mulOpposite (h : UniqueProds Gᵐᵒᵖ) : UniqueProds G where
@[to_additive] instance [h : UniqueProds G] : UniqueProds Gᵐᵒᵖ :=
of_mulOpposite <| (mulHom_image_iff <| MulEquiv.opOp G).mp h
+@[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
+ · exact (hu ha this he).2
+
+open MulOpposite in
+@[to_additive] theorem toIsCancelMul [UniqueProds G] : IsCancelMul G where
+ mul_left_cancel := toIsLeftCancelMul.mul_left_cancel
+ mul_right_cancel _ _ _ h :=
+ op_injective <| toIsLeftCancelMul.mul_left_cancel _ _ _ <| unop_injective h
+
+/-! Two theorems in [Andrzej Strojnowski, *A note on u.p. groups*][Strojnowski1980] -/
+
+/-- `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]
+ 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
+ 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⁻¹
+ have hcard : 1 < C.card ∨ 1 < D.card; · simp_rw [card_map]; exact hc.2.2
+ have hC : 1 ∈ C := mem_map.mpr ⟨a, ha, inv_mul_self a⟩
+ have hD : 1 ∈ D := mem_map.mpr ⟨b, hb, mul_inv_self b⟩
+ suffices : ∃ c ∈ C, ∃ d ∈ D, (c ≠ 1 ∨ d ≠ 1) ∧ UniqueMul C D c d
+ · simp_rw [mem_product]
+ obtain ⟨c, hc, d, hd, hne, hu'⟩ := this
+ obtain ⟨a0, ha0, rfl⟩ := mem_map.mp hc
+ obtain ⟨b0, hb0, rfl⟩ := mem_map.mp hd
+ refine ⟨(_, _), ⟨ha0, hb0⟩, (a, b), ⟨ha, hb⟩, ?_, fun a' b' ha' hb' he => ?_, hu⟩
+ simp_rw [Function.Embedding.coeFn_mk, Ne, inv_mul_eq_one, mul_inv_eq_one] at hne
+ · rwa [Ne, Prod.mk.inj_iff, not_and_or, eq_comm]
+ specialize hu' (mem_map_of_mem _ ha') (mem_map_of_mem _ hb')
+ simp_rw [Function.Embedding.coeFn_mk, mul_left_cancel_iff, mul_right_cancel_iff] at hu'
+ rw [mul_assoc, ← mul_assoc a', he, mul_assoc, mul_assoc] at hu'
+ exact hu' rfl
+ classical
+ let _ := Finset.mul (α := G) -- E = D⁻¹C, F = DC⁻¹
+ have := uniqueMul_of_nonempty (A := D.image (·⁻¹) * C) (B := D * C.image (·⁻¹)) ?_ ?_
+ · obtain ⟨e, he, f, hf, hu⟩ := this
+ clear_value C D
+ simp only [UniqueMul, mem_mul, mem_image] at he hf hu
+ obtain ⟨_, c1, ⟨d1, hd1, rfl⟩, hc1, rfl⟩ := he
+ obtain ⟨d2, _, hd2, ⟨c2, hc2, rfl⟩, rfl⟩ := hf
+ by_cases h12 : c1 ≠ 1 ∨ d2 ≠ 1
+ · refine ⟨c1, hc1, d2, hd2, h12, fun c3 d3 hc3 hd3 he => ?_⟩
+ specialize hu ⟨_, _, ⟨_, hd1, rfl⟩, hc3, rfl⟩ ⟨_, _, hd3, ⟨_, hc2, rfl⟩, rfl⟩
+ rw [mul_left_cancel_iff, mul_right_cancel_iff,
+ mul_assoc, ←mul_assoc c3, he, mul_assoc, mul_assoc] at hu; exact hu rfl
+ push_neg at h12; obtain ⟨rfl, rfl⟩ := h12
+ by_cases h21 : c2 ≠ 1 ∨ d1 ≠ 1
+ · refine ⟨c2, hc2, d1, hd1, h21, fun c4 d4 hc4 hd4 he => ?_⟩
+ specialize hu ⟨_, _, ⟨_, hd4, rfl⟩, hC, rfl⟩ ⟨_, _, hD, ⟨_, hc4, rfl⟩, rfl⟩
+ simpa only [mul_one, one_mul, ← mul_inv_rev, he, true_imp_iff, inv_inj, and_comm] using hu
+ push_neg at h21; obtain ⟨rfl, rfl⟩ := h21
+ rcases hcard with hC | hD
+ · obtain ⟨c, hc, hc1⟩ := exists_ne_of_one_lt_card hC 1
+ refine (hc1 ?_).elim
+ simpa using hu ⟨_, _, ⟨_, hD, rfl⟩, hc, rfl⟩ ⟨_, _, hD, ⟨_, hc, rfl⟩, rfl⟩
+ · obtain ⟨d, hd, hd1⟩ := exists_ne_of_one_lt_card hD 1
+ refine (hd1 ?_).elim
+ simpa using hu ⟨_, _, ⟨_, hd, rfl⟩, hC, rfl⟩ ⟨_, _, hd, ⟨_, hC, rfl⟩, rfl⟩
+ all_goals apply_rules [Nonempty.mul, Nonempty.image, Finset.Nonempty.map, hc.1, hc.2.1]
+
open UniqueMul in
@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
UniqueProds (∀ i, G i) where
Introduce TwoUniqueProds/Sums
: let R[G]
be a monoid algebra over a semiring R
without zero-divisors. A natural sufficient condition for R[G]
to have no zero-divisors is that G
has UniqueProds
, as is shown by MonoidAlgebra.instNoZeroDivisorsOfUniqueProds. Similarly, a natural sufficient condition for R[G]
to have only trivial units (of the form rg
with r
a unit in R
and g
a unit in G
) is that G
has TwoUniqueProds
, but we don't prove this yet in this PR. TwoUniqueProds G
is also a natural sufficient condition in order for factors of a homogeneous element in an algebra graded by G
without zero-divisors to themselves be homogeneous.
Show TwoUniqueProds
implies UniqueProds
: TwoUniqueProds.toUniqueProds
Strengthen of_Covariant_right/left
to have TwoUniqueProds
as conclusion
Extract of_image_filter
from the proof of the instance UniqueProds (∀ i, G i)
and use it also in the proof of TwoUniqueProds (∀ i, G i)
Use some private defs (starting from private abbrev I
) to transfer (Two)UniqueProds (∀ i, G i)
instances to (Two)UniqueProds (G × H)
Move the [Module ℚ G] : UniqueSums G
instance from NoZeroDivisors.lean to UniqueProds.lean and strengthen to TwoUniqueSums
New lemmas about UniqueMul:
of_card_le_one
, iff_card_le_one
, UniqueMul_of_TwoUniqueMul
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -5,15 +5,14 @@ Authors: Damiano Testa
-/
import Mathlib.Data.DFinsupp.Basic
import Mathlib.Data.Finset.Pointwise
-import Mathlib.Data.Finset.Preimage
-import Mathlib.Data.Finsupp.Defs
+import Mathlib.LinearAlgebra.Basis.VectorSpace
#align_import algebra.group.unique_prods from "leanprover-community/mathlib"@"d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce"
/-!
# Unique products and related notions
-A group `G` has *unique products* if for any two non-empty finite subsets `A, B ⊂ G`, there is an
+A group `G` has *unique products* if for any two non-empty finite subsets `A, B ⊆ G`, there is an
element `g ∈ A * B` that can be written uniquely as a product of an element of `A` and an element
of `B`. We call the formalization this property `UniqueProds`. Since the condition requires no
property of the group operation, we define it for a Type simply satisfying `Mul`. We also
@@ -68,14 +67,21 @@ variable {G H : Type*} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 := by simp [UniqueMul]
@[to_additive]
-theorem mt {G} [Mul G] {A B : Finset G} {a0 b0 : G} (h : UniqueMul A B a0 b0) :
+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 := by
+ rw [Finset.card_le_one_iff] at hA1 hB1
+ obtain ⟨a, ha⟩ := hA; obtain ⟨b, hb⟩ := hB
+ exact ⟨a, ha, b, hb, fun _ _ ha' hb' _ ↦ ⟨hA1 ha' ha, hB1 hb' hb⟩⟩
+
+@[to_additive]
+theorem mt (h : UniqueMul A B a0 b0) :
∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k ↦ by
contrapose! k
exact h ha hb k
#align unique_mul.mt UniqueMul.mt
@[to_additive]
-theorem subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0) :
+theorem subsingleton (h : UniqueMul A B a0 b0) :
Subsingleton { ab : G × G // ab.1 ∈ A ∧ ab.2 ∈ B ∧ ab.1 * ab.2 = a0 * b0 } :=
⟨fun ⟨⟨_a, _b⟩, ha, hb, ab⟩ ⟨⟨_a', _b'⟩, ha', hb', ab'⟩ ↦
Subtype.ext <|
@@ -85,7 +91,7 @@ theorem subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0) :
#align unique_add.subsingleton UniqueAdd.subsingleton
@[to_additive]
-theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0) :
+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 } := by
rintro ⟨x1, y1⟩ (hx : x1 ∈ A ∧ y1 ∈ B ∧ x1 * y1 = a0 * b0) ⟨x2, y2⟩
(hy : x2 ∈ A ∧ y2 ∈ B ∧ x2 * y2 = a0 * b0)
@@ -99,29 +105,39 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
-- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
@[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 :=
- ⟨fun _ ↦ ⟨(a0, b0), ⟨Finset.mem_product.mpr ⟨aA, bB⟩, rfl, by simp⟩, by simpa⟩,
- fun h ↦ h.elim₂
+ UniqueMul A B a0 b0 ↔ ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = a0 * b0 :=
+ ⟨fun _ ↦ ⟨(a0, b0), ⟨Finset.mk_mem_product aA bB, rfl⟩, by simpa⟩,
+ fun h ↦ h.elim
(by
- rintro ⟨x1, x2⟩ _ _ J x y hx hy l
- rcases Prod.mk.inj_iff.mp (J (a0, b0) (Finset.mk_mem_product aA bB) rfl) with ⟨rfl, rfl⟩
- exact Prod.mk.inj_iff.mp (J (x, y) (Finset.mk_mem_product hx hy) l))⟩
-#align unique_mul.iff_exists_unique UniqueMul.iff_existsUnique
-#align unique_add.iff_exists_unique UniqueAdd.iff_existsUnique
+ rintro ⟨x1, x2⟩ _ J x y hx hy l
+ rcases Prod.mk.inj_iff.mp (J (a0, b0) ⟨Finset.mk_mem_product aA bB, rfl⟩) with ⟨rfl, rfl⟩
+ exact Prod.mk.inj_iff.mp (J (x, y) ⟨Finset.mk_mem_product hx hy, l⟩))⟩
+#align unique_mul.iff_exists_unique UniqueMul.iff_existsUniqueₓ
+#align unique_add.iff_exists_unique UniqueAdd.iff_existsUniqueₓ
+
+open Finset in
+@[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 := by
+ simp_rw [card_le_one_iff, mem_filter, mem_product]
+ refine ⟨fun h p1 p2 ⟨⟨ha1, hb1⟩, he1⟩ ⟨⟨ha2, hb2⟩, he2⟩ ↦ ?_, fun h a b ha hb he ↦ ?_⟩
+ · have h1 := h ha1 hb1 he1; have h2 := h ha2 hb2 he2
+ ext; rw [h1.1, h2.1]; rw [h1.2, h2.2]
+ · exact Prod.ext_iff.1 (@h (a, b) (a0, b0) ⟨⟨ha, hb⟩, he⟩ ⟨⟨ha0, hb0⟩, rfl⟩)
-- Porting note: mathport warning: expanding binder collection
-- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
@[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 :=
+ ∃ g : G, ∃! ab, ab ∈ A ×ˢ B ∧ ab.1 * ab.2 = g :=
⟨fun ⟨a0, b0, hA, hB, h⟩ ↦ ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ ↦ by
have h' := h
rcases h' with ⟨⟨a, b⟩, ⟨hab, rfl, -⟩, -⟩
cases' Finset.mem_product.mp hab with ha hb
exact ⟨a, b, ha, hb, (iff_existsUnique ha hb).mpr h⟩⟩
-#align unique_mul.exists_iff_exists_exists_unique UniqueMul.exists_iff_exists_existsUnique
-#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUnique
+#align unique_mul.exists_iff_exists_exists_unique UniqueMul.exists_iff_exists_existsUniqueₓ
+#align unique_add.exists_iff_exists_exists_unique UniqueAdd.exists_iff_exists_existsUniqueₓ
/-- `UniqueMul` is preserved by inverse images under injective, multiplicative maps. -/
@[to_additive "`UniqueAdd` is preserved by inverse images under injective, additive maps."]
@@ -145,11 +161,11 @@ 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 := by
simp_rw [UniqueMul, Finset.mem_image]
- refine' ⟨fun h a b ha hb ab ↦ _, fun h ↦ _⟩
+ refine ⟨fun h a b ha hb ab ↦ ?_, fun h _ _ ↦ ?_⟩
· rw [← hf.eq_iff, map_mul, map_mul] at ab
have := h ⟨a, ha, rfl⟩ ⟨b, hb, rfl⟩ ab
exact ⟨hf this.1, hf this.2⟩
- · rintro _ _ ⟨a, aA, rfl⟩ ⟨b, bB, rfl⟩ ab
+ · rintro ⟨a, aA, rfl⟩ ⟨b, bB, rfl⟩ ab
simp only [← map_mul, hf.eq_iff] at ab ⊢
exact h aA bB ab
#align unique_mul.mul_hom_image_iff UniqueMul.mulHom_image_iff
@@ -164,10 +180,7 @@ See `UniqueMul.mulHom_image_iff` for a version with swapped bundling. -/
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 := by
- classical
- convert @mulHom_image_iff G H _ _ A B a0 b0 _ ⟨f, mul⟩ f.2 using 2 <;>
- · ext
- simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
+ classical simp_rw [← mulHom_image_iff ⟨f, mul⟩ f.2, Finset.map_eq_image]; rfl
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
@@ -177,22 +190,13 @@ open Finset MulOpposite
@[to_additive]
theorem of_mulOpposite
(h : UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0)) :
- UniqueMul A B a0 b0 := by
- intros a b aA bB ab
- have := h (mem_map_of_mem _ bB) (mem_map_of_mem _ aA) (by simpa using congr_arg op ab)
- simpa [and_comm] using this
+ UniqueMul A B a0 b0 := fun a b aA bB ab ↦ by
+ simpa [and_comm] using h (mem_map_of_mem _ bB) (mem_map_of_mem _ aA) (congr_arg op ab)
@[to_additive]
theorem to_mulOpposite (h : UniqueMul A B a0 b0) :
- UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) := by
- refine of_mulOpposite (G := MulOpposite G) <| fun a b ha hb hab ↦ ?_
- simp only [mem_map, Function.Embedding.coeFn_mk, exists_exists_and_eq_and] at ha hb
- rcases ha with ⟨a, ha, rfl⟩
- rcases hb with ⟨b, hb, rfl⟩
- rw [op_inj, op_inj, op_inj, op_inj]
- apply h ha hb ?_
- apply_fun op ∘ op using op_injective.comp op_injective
- exact hab
+ UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) :=
+ of_mulOpposite (by simp_rw [map_map]; exact (mulHom_map_iff _ fun _ _ ↦ by rfl).mpr h)
@[to_additive]
theorem iff_mulOpposite :
@@ -202,6 +206,18 @@ theorem iff_mulOpposite :
end Opposites
+open Finset in
+@[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 := fun a b ha hb he ↦ by
+ specialize huH (mem_image_of_mem _ ha) (mem_image_of_mem _ hb)
+ rw [← map_mul, he, map_mul, hae, hbe] at huH
+ refine huG ?_ ?_ he <;> rw [mem_filter]
+ exacts [⟨ha, (huH rfl).1⟩, ⟨hb, (huH rfl).2⟩]
+
end UniqueMul
/-- Let `G` be a Type with addition. `UniqueSums G` asserts that any two non-empty
@@ -211,7 +227,7 @@ 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
+ ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueAdd A B a0 b0
#align unique_sums UniqueSums
/-- Let `G` be a Type with multiplication. `UniqueProds G` asserts that any two non-empty
@@ -221,16 +237,55 @@ 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
+ ∀ {A B : Finset G}, A.Nonempty → B.Nonempty → ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0
#align unique_prods UniqueProds
attribute [to_additive] UniqueProds
+/-- 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
+
+/-- 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
+
+attribute [to_additive] TwoUniqueProds
+
+@[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 := by
+ by_cases hc : A.card ≤ 1 ∧ B.card ≤ 1
+ · exact UniqueMul.of_card_le_one hA hB hc.1 hc.2
+ simp_rw [not_and_or, not_le] at hc
+ rw [← Finset.card_pos] at hA hB
+ obtain ⟨p, hp, _, _, _, hu, _⟩ := h (Nat.one_lt_mul_iff.mpr ⟨hA, hB, hc⟩)
+ rw [Finset.mem_product] at hp
+ exact ⟨p.1, hp.1, p.2, hp.2, hu⟩
+
+@[to_additive] instance TwoUniqueProds.toUniqueProds (G) [Mul G] [TwoUniqueProds G] :
+ UniqueProds G where
+ uniqueMul_of_nonempty := uniqueMul_of_twoUniqueMul uniqueMul_of_one_lt_card
+
namespace Multiplicative
instance {M} [Add M] [UniqueSums M] : UniqueProds (Multiplicative M) where
uniqueMul_of_nonempty := UniqueSums.uniqueAdd_of_nonempty (G := M)
+instance {M} [Add M] [TwoUniqueSums M] : TwoUniqueProds (Multiplicative M) where
+ uniqueMul_of_one_lt_card := TwoUniqueSums.uniqueAdd_of_one_lt_card (G := M)
+
end Multiplicative
namespace Additive
@@ -238,70 +293,39 @@ namespace Additive
instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M) where
uniqueAdd_of_nonempty := UniqueProds.uniqueMul_of_nonempty (G := M)
+instance {M} [Mul M] [TwoUniqueProds M] : TwoUniqueSums (Additive M) where
+ uniqueAdd_of_one_lt_card := TwoUniqueProds.uniqueMul_of_one_lt_card (G := M)
+
end Additive
#noalign covariants.to_unique_prods
#noalign covariants.to_unique_sums
-namespace UniqueProds
+universe u v
+variable (G : Type u) (H : Type v) [Mul G] [Mul H]
-variable {G H : Type*} [Mul G] [Mul H]
+private abbrev I : Bool → Type max u v := Bool.rec (ULift.{v} G) (ULift.{u} H)
+@[to_additive] private instance : ∀ b, Mul (I G H b) := Bool.rec ULift.mul ULift.mul
+@[to_additive] private instance : Mul (∀ b, I G H b) := inferInstance
+@[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 (_|_) <;> rfl⟩
+@[to_additive] private def downMulHom : ULift G →ₙ* G := ⟨ULift.down, fun _ _ ↦ rfl⟩
-open Finset MulOpposite in
-@[to_additive]
-theorem of_mulOpposite (h : @UniqueProds Gᵐᵒᵖ (MulOpposite.mul G)) :
- UniqueProds G :=
-⟨fun hA hB =>
- let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
- let ⟨y, yB, x, xA, hxy⟩ := h.uniqueMul_of_nonempty (hB.map (f := f)) (hA.map (f := f))
- ⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩⟩
+variable {G H}
--- see Note [lower instance priority]
-/-- 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 `UniqueProds`. -/
-@[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 `UniqueSums`." ]
-instance (priority := 100) of_Covariant_right [IsRightCancelMul G]
- [LinearOrder G] [CovariantClass G G (· * ·) (· < ·)] :
- UniqueProds G where
- uniqueMul_of_nonempty {A B} hA hB := by
- obtain ⟨a0, b0, ha0, hb0, he⟩ := Finset.mem_mul.mp (Finset.max'_mem _ <| hA.mul hB)
- refine ⟨a0, ha0, b0, hb0, fun a b ha hb he' => ?_⟩
- obtain hl | rfl | hl := lt_trichotomy b b0
- · refine ((he'.trans he ▸ mul_lt_mul_left' hl a).not_le <| Finset.le_max' _ (a * b0) ?_).elim
- exact Finset.mem_mul.mpr ⟨a, b0, ha, hb0, rfl⟩
- · exact ⟨mul_right_cancel he', rfl⟩
- · refine ((he ▸ mul_lt_mul_left' hl a0).not_le <| Finset.le_max' _ (a0 * b) ?_).elim
- exact Finset.mem_mul.mpr ⟨a0, b, ha0, hb, rfl⟩
-
-open MulOpposite in
--- see Note [lower instance priority]
-/-- 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 `UniqueProds`. -/
-@[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 `UniqueSums`." ]
-instance (priority := 100) of_Covariant_left [IsLeftCancelMul G]
- [LinearOrder G] [CovariantClass G G (Function.swap (· * ·)) (· < ·)] :
- UniqueProds G :=
-let _ := LinearOrder.lift' (unop : Gᵐᵒᵖ → G) unop_injective
-let _ : CovariantClass Gᵐᵒᵖ Gᵐᵒᵖ (· * ·) (· < ·) :=
-{ elim := fun _ _ _ bc =>
- have : StrictMono (unop (α := G)) := fun _ _ => id
- mul_lt_mul_right' (α := G) bc (unop _) }
-of_mulOpposite of_Covariant_right
+namespace UniqueProds
open Finset
+
@[to_additive]
theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
- UniqueProds H := by
- refine ⟨fun {A B} A0 B0 => ?_⟩
- 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⟩
+ 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⟩
+ exact ⟨a', ha', b', hb', (UniqueMul.mulHom_image_iff f hf).mp h⟩
/-- `UniqueProd` is preserved under multiplicative equivalences. -/
@[to_additive "`UniqueSums` is preserved under additive equivalences."]
@@ -309,61 +333,47 @@ theorem mulHom_image_iff (f : G ≃* H) :
UniqueProds G ↔ UniqueProds H :=
⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
-@[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) where
- uniqueMul_of_nonempty {A B} hA hB := by
- classical
- obtain ⟨aG, hA, bG, hB, hG⟩ := uniqueMul_of_nonempty (hA.image Prod.fst) (hB.image Prod.fst)
- rw [mem_image, ← filter_nonempty_iff] at hA hB
- obtain ⟨aH, hA, bH, hB, hH⟩ := uniqueMul_of_nonempty (hA.image Prod.snd) (hB.image Prod.snd)
- simp_rw [mem_image, mem_filter] at hA hB
- refine ⟨(aG, aH), ?_, (bG, bH), ?_, fun a b ha hb he => ?_⟩
- · obtain ⟨a, ⟨ha, rfl⟩, rfl⟩ := hA; exact ha
- · obtain ⟨b, ⟨hb, rfl⟩, rfl⟩ := hB; exact hb
- rw [Prod.ext_iff] at he
- specialize hG (mem_image.mpr ⟨a, ha, rfl⟩) (mem_image.mpr ⟨b, hb, rfl⟩) he.1
- specialize hH _ _ he.2
- all_goals try simp_rw [mem_image, mem_filter]
- exacts [⟨a, ⟨ha, hG.1⟩, rfl⟩, ⟨b, ⟨hb, hG.2⟩, rfl⟩, ⟨Prod.ext hG.1 hH.1, Prod.ext hG.2 hH.2⟩]
+open Finset MulOpposite in
+@[to_additive]
+theorem of_mulOpposite (h : UniqueProds Gᵐᵒᵖ) : UniqueProds G where
+ uniqueMul_of_nonempty hA hB :=
+ let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
+ let ⟨y, yB, x, xA, hxy⟩ := h.uniqueMul_of_nonempty (hB.map (f := f)) (hA.map (f := f))
+ ⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩
+
+@[to_additive] instance [h : UniqueProds G] : UniqueProds Gᵐᵒᵖ :=
+ of_mulOpposite <| (mulHom_image_iff <| MulEquiv.opOp G).mp h
+open UniqueMul in
@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
UniqueProds (∀ i, G i) where
uniqueMul_of_nonempty {A} := by
classical
- let _ := Finset.isWellFounded_ssubset (α := ∀ i, G i) -- why need this?
+ let _ := isWellFounded_ssubset (α := ∀ i, G i) -- why need this?
apply IsWellFounded.induction (· ⊂ ·) A; intro A ihA B hA
apply IsWellFounded.induction (· ⊂ ·) B; intro B ihB hB
- obtain hc | ⟨i, hc⟩ : (A.card ≤ 1 ∧ B.card ≤ 1) ∨
- ∃ i, (∃ a1 ∈ A, ∃ a2 ∈ A, a1 i ≠ a2 i) ∨ (∃ b1 ∈ B, ∃ b2 ∈ B, b1 i ≠ b2 i)
- · obtain hA1 | h1A := le_or_lt A.card 1
- · obtain hB1 | h1B := le_or_lt B.card 1
- · exact Or.inl ⟨hA1, hB1⟩
- obtain ⟨b1, h1, b2, h2, hne⟩ := Finset.one_lt_card.mp h1B
- obtain ⟨i, hne⟩ := Function.ne_iff.mp hne
- exact Or.inr ⟨i, Or.inr ⟨b1, h1, b2, h2, hne⟩⟩
- obtain ⟨a1, h1, a2, h2, hne⟩ := Finset.one_lt_card.mp h1A
- obtain ⟨i, hne⟩ := Function.ne_iff.mp hne
- exact Or.inr ⟨i, Or.inl ⟨a1, h1, a2, h2, hne⟩⟩
- · obtain ⟨a0, ha0⟩ := hA; obtain ⟨b0, hb0⟩ := hB
- simp_rw [Finset.card_le_one_iff] at hc
- exact ⟨a0, ha0, b0, hb0, fun a b ha hb _ => ⟨hc.1 ha ha0, hc.2 hb hb0⟩⟩
+ by_cases hc : A.card ≤ 1 ∧ B.card ≤ 1
+ · exact of_card_le_one hA hB hc.1 hc.2
+ simp_rw [not_and_or, not_le] at hc
+ obtain ⟨i, hc⟩ := exists_or.mpr (hc.imp exists_of_one_lt_card_pi exists_of_one_lt_card_pi)
obtain ⟨ai, hA, bi, hB, hi⟩ := uniqueMul_of_nonempty (hA.image (· i)) (hB.image (· i))
rw [mem_image, ← filter_nonempty_iff] at hA hB
let A' := A.filter (· i = ai); let B' := B.filter (· i = bi)
obtain ⟨a0, ha0, b0, hb0, hu⟩ : ∃ a0 ∈ A', ∃ b0 ∈ B', UniqueMul A' B' a0 b0
- · rcases hc with ⟨a1, h1, a2, h2, hne⟩ | ⟨b1, h1, b2, h2, hne⟩
- · refine ihA _ ⟨A.filter_subset _, fun h => ?_⟩ hA hB
- obtain rfl | hai := eq_or_ne (a1 i) ai
- exacts [hne (mem_filter.mp <| h h2).2.symm, hai (mem_filter.mp <| h h1).2]
- by_cases hA' : A' = A
- · rw [hA']; refine ihB _ ⟨B.filter_subset _, fun h => ?_⟩ hB
- obtain rfl | hbi := eq_or_ne (b1 i) bi
- exacts [hne (mem_filter.mp <| h h2).2.symm, hbi (mem_filter.mp <| h h1).2]
- exact ihA A' ((A.filter_subset _).ssubset_of_ne hA') hA hB
+ · rcases hc with hc | hc; · exact ihA A' (hc.2 ai) hA hB
+ by_cases hA' : A' = A; rw [hA']
+ exacts [ihB B' (hc.2 bi) hB, ihA A' ((A.filter_subset _).ssubset_of_ne hA') hA hB]
rw [mem_filter] at ha0 hb0
- refine ⟨a0, ha0.1, b0, hb0.1, fun a b ha hb he => ?_⟩
- specialize hi (mem_image_of_mem _ ha) (mem_image_of_mem _ hb) ?_
- · refine (congr_arg (· i) he).trans ?_; rw [← ha0.2, ← hb0.2]; rfl
- exact hu (mem_filter.mpr ⟨ha, hi.1⟩) (mem_filter.mpr ⟨hb, hi.2⟩) he
+ exact ⟨a0, ha0.1, b0, hb0.1, of_image_filter (Pi.evalMulHom G i) ha0.2 hb0.2 hi hu⟩
+
+open ULift in
+@[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) := by
+ have : ∀ b, UniqueProds (I G H b) := Bool.rec ?_ ?_
+ · exact mulHom_image_of_injective (downMulHom H) down_injective ‹_›
+ · refine mulHom_image_of_injective (Prod.upMulHom G H) (fun x y he => Prod.ext ?_ ?_)
+ (instUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
+ exacts [congr_fun he false, congr_fun he true]
+ · exact mulHom_image_of_injective (downMulHom G) down_injective ‹_›
end UniqueProds
@@ -375,3 +385,148 @@ instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums
instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) :=
UniqueSums.addHom_image_of_injective
Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance
+
+namespace TwoUniqueProds
+
+open Finset
+
+@[to_additive]
+theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f)
+ (uG : TwoUniqueProds G) : TwoUniqueProds H where
+ uniqueMul_of_one_lt_card {A B} hc := by
+ classical
+ simp_rw [← card_map ⟨f, hf⟩] at hc
+ obtain ⟨⟨a1, b1⟩, h1, ⟨a2, b2⟩, h2, hne, hu1, hu2⟩ := uG.uniqueMul_of_one_lt_card hc
+ simp only [mem_product, mem_map] at h1 h2 ⊢
+ obtain ⟨⟨a1, ha1, rfl⟩, ⟨b1, hb1, rfl⟩⟩ := h1
+ obtain ⟨⟨a2, ha2, rfl⟩, ⟨b2, hb2, rfl⟩⟩ := h2
+ refine ⟨(a1, b1), ⟨ha1, hb1⟩, (a2, b2), ⟨ha2, hb2⟩, ?_, ?_, ?_⟩
+ · rw [Ne, Prod.ext_iff] at hne ⊢; simp_rw [← hf.eq_iff]; exact hne
+ all_goals apply (UniqueMul.mulHom_map_iff ⟨f, hf⟩ f.2).mp
+ exacts [hu1, hu2]
+
+/-- `TwoUniqueProd` is preserved under multiplicative equivalences. -/
+@[to_additive "`TwoUniqueSums` is preserved under additive equivalences."]
+theorem mulHom_image_iff (f : G ≃* H) : TwoUniqueProds G ↔ TwoUniqueProds H :=
+⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+
+@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, TwoUniqueProds (G i)] :
+ TwoUniqueProds (∀ i, G i) where
+ uniqueMul_of_one_lt_card {A} := by
+ classical
+ let _ := isWellFounded_ssubset (α := ∀ i, G i) -- why need this?
+ apply IsWellFounded.induction (· ⊂ ·) A; intro A ihA B
+ apply IsWellFounded.induction (· ⊂ ·) B; intro B ihB hc
+ obtain ⟨hA, hB, hc⟩ := Nat.one_lt_mul_iff.mp hc
+ rw [card_pos] at hA hB
+ obtain ⟨i, hc⟩ := exists_or.mpr (hc.imp exists_of_one_lt_card_pi exists_of_one_lt_card_pi)
+ obtain ⟨p1, h1, p2, h2, hne, hi1, hi2⟩ := uniqueMul_of_one_lt_card (Nat.one_lt_mul_iff.mpr
+ ⟨card_pos.2 (hA.image _), card_pos.2 (hB.image _), hc.imp And.left And.left⟩)
+ simp_rw [mem_product, mem_image, ← filter_nonempty_iff] at h1 h2
+ replace h1 := uniqueMul_of_twoUniqueMul ?_ h1.1 h1.2
+ replace h2 := uniqueMul_of_twoUniqueMul ?_ h2.1 h2.2
+ · obtain ⟨a1, ha1, b1, hb1, hu1⟩ := h1
+ obtain ⟨a2, ha2, b2, hb2, hu2⟩ := h2
+ rw [mem_filter] at ha1 hb1 ha2 hb2
+ simp_rw [mem_product]
+ refine ⟨(a1, b1), ⟨ha1.1, hb1.1⟩, (a2, b2), ⟨ha2.1, hb2.1⟩, ?_,
+ UniqueMul.of_image_filter (Pi.evalMulHom G i) ha1.2 hb1.2 hi1 hu1,
+ UniqueMul.of_image_filter (Pi.evalMulHom G i) ha2.2 hb2.2 hi2 hu2⟩
+ contrapose! hne; rw [Prod.mk.inj_iff] at hne ⊢
+ rw [← ha1.2, ← hb1.2, ← ha2.2, ← hb2.2, hne.1, hne.2]; exact ⟨rfl, rfl⟩
+ all_goals
+ rcases hc with hc | hc; · exact ihA _ (hc.2 _)
+ by_cases hA : A.filter (· i = _) = A; rw [hA]
+ exacts [ihB _ (hc.2 _), ihA _ ((A.filter_subset _).ssubset_of_ne hA)]
+
+open ULift in
+@[to_additive] instance [TwoUniqueProds G] [TwoUniqueProds H] : TwoUniqueProds (G × H) := by
+ have : ∀ b, TwoUniqueProds (I G H b) := Bool.rec ?_ ?_
+ · exact mulHom_image_of_injective (downMulHom H) down_injective ‹_›
+ · refine mulHom_image_of_injective (Prod.upMulHom G H) (fun x y he ↦ Prod.ext ?_ ?_)
+ (instTwoUniqueProdsForAllInstMul <| I G H) <;> apply up_injective
+ exacts [congr_fun he false, congr_fun he true]
+ · exact mulHom_image_of_injective (downMulHom G) down_injective ‹_›
+
+open MulOpposite in
+@[to_additive]
+theorem of_mulOpposite (h : TwoUniqueProds Gᵐᵒᵖ) : TwoUniqueProds G where
+ uniqueMul_of_one_lt_card hc := by
+ let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
+ rw [← card_map f, ← card_map f, mul_comm] at hc
+ obtain ⟨p1, h1, p2, h2, hne, hu1, hu2⟩ := h.uniqueMul_of_one_lt_card hc
+ simp_rw [mem_product] at h1 h2 ⊢
+ refine ⟨(_, _), ⟨?_, ?_⟩, (_, _), ⟨?_, ?_⟩, ?_, hu1.of_mulOpposite, hu2.of_mulOpposite⟩
+ pick_goal 5
+ · contrapose! hne; rw [Prod.ext_iff] at hne ⊢
+ exact ⟨unop_injective hne.2, unop_injective hne.1⟩
+ all_goals apply (mem_map' f).mp
+ exacts [h1.2, h1.1, h2.2, h2.1]
+
+@[to_additive] instance [h : TwoUniqueProds G] : TwoUniqueProds Gᵐᵒᵖ :=
+ of_mulOpposite <| (mulHom_image_iff <| MulEquiv.opOp G).mp h
+
+-- see Note [lower instance priority]
+/-- 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 where
+ uniqueMul_of_one_lt_card {A B} hc := by
+ obtain ⟨hA, hB, -⟩ := Nat.one_lt_mul_iff.mp hc
+ rw [card_pos] at hA hB
+ rw [← card_product] at hc
+ obtain ⟨a0, b0, ha0, hb0, he0⟩ := mem_mul.mp (max'_mem _ <| hA.mul hB)
+ obtain ⟨a1, b1, ha1, hb1, he1⟩ := mem_mul.mp (min'_mem _ <| hA.mul hB)
+ have : UniqueMul A B a0 b0
+ · intro a b ha hb he
+ obtain hl | rfl | hl := lt_trichotomy b b0
+ · exact ((he0 ▸ he ▸ mul_lt_mul_left' hl a).not_le <| le_max' _ _ <| mul_mem_mul ha hb0).elim
+ · exact ⟨mul_right_cancel he, rfl⟩
+ · exact ((he0 ▸ mul_lt_mul_left' hl a0).not_le <| le_max' _ _ <| mul_mem_mul ha0 hb).elim
+ refine ⟨_, mk_mem_product ha0 hb0, _, mk_mem_product ha1 hb1, fun he ↦ ?_, this, ?_⟩
+ · rw [Prod.mk.inj_iff] at he; rw [he.1, he.2, he1] at he0
+ obtain ⟨⟨a2, b2⟩, h2, hne⟩ := exists_ne_of_one_lt_card hc (a0, b0)
+ rw [mem_product] at h2
+ refine (min'_lt_max' _ (mul_mem_mul ha0 hb0) (mul_mem_mul h2.1 h2.2) fun he ↦ hne ?_).ne he0
+ exact Prod.ext_iff.mpr (this h2.1 h2.2 he.symm)
+ · intro a b ha hb he
+ obtain hl | rfl | hl := lt_trichotomy b b1
+ · exact ((he1 ▸ mul_lt_mul_left' hl a1).not_le <| min'_le _ _ <| mul_mem_mul ha1 hb).elim
+ · exact ⟨mul_right_cancel he, rfl⟩
+ · exact ((he1 ▸ he ▸ mul_lt_mul_left' hl a).not_le <| min'_le _ _ <| mul_mem_mul ha hb1).elim
+
+open MulOpposite in
+-- see Note [lower instance priority]
+/-- 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 :=
+ let _ := LinearOrder.lift' (unop : Gᵐᵒᵖ → G) unop_injective
+ let _ : CovariantClass Gᵐᵒᵖ Gᵐᵒᵖ (· * ·) (· < ·) :=
+ { elim := fun _ _ _ bc ↦ mul_lt_mul_right' (α := G) bc (unop _) }
+ of_mulOpposite of_Covariant_right
+
+end TwoUniqueProds
+
+instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, TwoUniqueSums (G i)] :
+ TwoUniqueSums (Π₀ i, G i) :=
+ TwoUniqueSums.addHom_image_of_injective
+ DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance
+
+instance {ι G} [AddZeroClass G] [TwoUniqueSums G] : TwoUniqueSums (ι →₀ G) :=
+ TwoUniqueSums.addHom_image_of_injective
+ Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance
+
+/-- 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 :=
+ TwoUniqueSums.addHom_image_of_injective _ (Basis.ofVectorSpace ℚ G).repr.injective inferInstance
Add UniqueProds/Sums
and NoZeroDivisors
instances.
This has recently been prompted by the port of the Lindemann-Weierstrass Theorem, but the results are self-contained. Instances such as the ones in this PR are the reasons why UniqueProds/Sums
were introduced.
Affected files:
Algebra/
Group/UniqueProds.lean
MonoidAlgebra/NoZeroDivisors.lean
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -3,7 +3,10 @@ Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa
-/
+import Mathlib.Data.DFinsupp.Basic
+import Mathlib.Data.Finset.Pointwise
import Mathlib.Data.Finset.Preimage
+import Mathlib.Data.Finsupp.Defs
#align_import algebra.group.unique_prods from "leanprover-community/mathlib"@"d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce"
@@ -45,7 +48,6 @@ about the grading type and then a generic statement of the form "look at the coe
The file `Algebra/MonoidAlgebra/NoZeroDivisors` contains several examples of this use.
-/
-
/-- 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`. -/
@@ -203,7 +205,7 @@ end Opposites
end UniqueMul
/-- Let `G` be a Type with addition. `UniqueSums G` asserts that any two non-empty
-finite subsets of `A` have the `UniqueAdd` property, with respect to some element of their
+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
@@ -238,52 +240,138 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M) where
end Additive
--- see Note [lower instance priority]
-/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
-is 'very monotone', then `A` also has `UniqueProds`. -/
-@[to_additive
- "This instance asserts that if `A` has an addition, a linear order, and addition
-is 'very monotone', then `A` also has `UniqueSums`."]
-instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
- [CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
- [ContravariantClass A A (· * ·) (· ≤ ·)] : UniqueProds A where
- uniqueMul_of_nonempty {A B} hA hB :=
- ⟨_, A.max'_mem ‹_›, _, B.max'_mem ‹_›, fun a b ha hb ↦
- (mul_eq_mul_iff_eq_and_eq (Finset.le_max' _ _ ‹_›) (Finset.le_max' _ _ ‹_›)).mp⟩
-#align covariants.to_unique_prods Covariants.to_uniqueProds
-#align covariants.to_unique_sums Covariants.to_uniqueSums
+#noalign covariants.to_unique_prods
+#noalign covariants.to_unique_sums
namespace UniqueProds
-@[to_additive (attr := nontriviality, simp)]
-theorem of_subsingleton {G : Type*} [Mul G] [Subsingleton G] : UniqueProds G where
- uniqueMul_of_nonempty {A B} | ⟨a, hA⟩, ⟨b, hB⟩ => ⟨a, hA, b, hB, by simp⟩
+variable {G H : Type*} [Mul G] [Mul H]
open Finset MulOpposite in
@[to_additive]
-theorem of_mulOpposite (G : Type*) [Mul G] (h : UniqueProds Gᵐᵒᵖ) :
+theorem of_mulOpposite (h : @UniqueProds Gᵐᵒᵖ (MulOpposite.mul G)) :
UniqueProds G :=
- ⟨fun hA hB =>
- let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
- let ⟨y, yB, x, xA, hxy⟩ := h.uniqueMul_of_nonempty (hB.map (f := f)) (hA.map (f := f))
- ⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩⟩
+⟨fun hA hB =>
+ let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
+ let ⟨y, yB, x, xA, hxy⟩ := h.uniqueMul_of_nonempty (hB.map (f := f)) (hA.map (f := f))
+ ⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩⟩
+
+-- see Note [lower instance priority]
+/-- 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 `UniqueProds`. -/
+@[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 `UniqueSums`." ]
+instance (priority := 100) of_Covariant_right [IsRightCancelMul G]
+ [LinearOrder G] [CovariantClass G G (· * ·) (· < ·)] :
+ UniqueProds G where
+ uniqueMul_of_nonempty {A B} hA hB := by
+ obtain ⟨a0, b0, ha0, hb0, he⟩ := Finset.mem_mul.mp (Finset.max'_mem _ <| hA.mul hB)
+ refine ⟨a0, ha0, b0, hb0, fun a b ha hb he' => ?_⟩
+ obtain hl | rfl | hl := lt_trichotomy b b0
+ · refine ((he'.trans he ▸ mul_lt_mul_left' hl a).not_le <| Finset.le_max' _ (a * b0) ?_).elim
+ exact Finset.mem_mul.mpr ⟨a, b0, ha, hb0, rfl⟩
+ · exact ⟨mul_right_cancel he', rfl⟩
+ · refine ((he ▸ mul_lt_mul_left' hl a0).not_le <| Finset.le_max' _ (a0 * b) ?_).elim
+ exact Finset.mem_mul.mpr ⟨a0, b, ha0, hb, rfl⟩
open MulOpposite in
-@[to_additive (attr := simp)]
-theorem iff_mulOpposite (G : Type*) [Mul G] :
- UniqueProds Gᵐᵒᵖ ↔ UniqueProds G := by
- refine ⟨of_mulOpposite G, fun h ↦ of_mulOpposite (Gᵐᵒᵖ) ⟨fun {A B} hA hB ↦ ?_⟩⟩
+-- see Note [lower instance priority]
+/-- 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 `UniqueProds`. -/
+@[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 `UniqueSums`." ]
+instance (priority := 100) of_Covariant_left [IsLeftCancelMul G]
+ [LinearOrder G] [CovariantClass G G (Function.swap (· * ·)) (· < ·)] :
+ UniqueProds G :=
+let _ := LinearOrder.lift' (unop : Gᵐᵒᵖ → G) unop_injective
+let _ : CovariantClass Gᵐᵒᵖ Gᵐᵒᵖ (· * ·) (· < ·) :=
+{ elim := fun _ _ _ bc =>
+ have : StrictMono (unop (α := G)) := fun _ _ => id
+ mul_lt_mul_right' (α := G) bc (unop _) }
+of_mulOpposite of_Covariant_right
+
+open Finset
+@[to_additive]
+theorem mulHom_image_of_injective (f : H →ₙ* G) (hf : Function.Injective f) (uG : UniqueProds G) :
+ UniqueProds H := by
+ refine ⟨fun {A B} A0 B0 => ?_⟩
classical
- let f : Gᵐᵒᵖᵐᵒᵖ ↪ G := ⟨_, unop_injective.comp unop_injective⟩
- obtain ⟨a0, ha0, b0, hb0, d⟩ :=
- h.uniqueMul_of_nonempty (Finset.Nonempty.map (f := f) hA) (Finset.Nonempty.map (f := f) hB)
- simp only [Finset.mem_map, Function.Embedding.coeFn_mk, Function.comp_apply] at ha0 hb0
- rcases ha0 with ⟨a0, ha0, rfl⟩
- rcases hb0 with ⟨b0, hb0, rfl⟩
- refine ⟨a0, ha0, b0, hb0, ?_⟩
- apply (UniqueMul.mulHom_map_iff (H := G) (⟨_, unop_injective.comp unop_injective⟩) ?_).mp
- · simp only [Function.Embedding.coeFn_mk, Function.comp_apply]
- convert d
- · simp only [Function.Embedding.coeFn_mk, Function.comp_apply, unop_mul, implies_true]
+ 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⟩
+
+/-- `UniqueProd` is preserved under multiplicative equivalences. -/
+@[to_additive "`UniqueSums` is preserved under additive equivalences."]
+theorem mulHom_image_iff (f : G ≃* H) :
+ UniqueProds G ↔ UniqueProds H :=
+⟨mulHom_image_of_injective f.symm f.symm.injective, mulHom_image_of_injective f f.injective⟩
+
+@[to_additive] instance [UniqueProds G] [UniqueProds H] : UniqueProds (G × H) where
+ uniqueMul_of_nonempty {A B} hA hB := by
+ classical
+ obtain ⟨aG, hA, bG, hB, hG⟩ := uniqueMul_of_nonempty (hA.image Prod.fst) (hB.image Prod.fst)
+ rw [mem_image, ← filter_nonempty_iff] at hA hB
+ obtain ⟨aH, hA, bH, hB, hH⟩ := uniqueMul_of_nonempty (hA.image Prod.snd) (hB.image Prod.snd)
+ simp_rw [mem_image, mem_filter] at hA hB
+ refine ⟨(aG, aH), ?_, (bG, bH), ?_, fun a b ha hb he => ?_⟩
+ · obtain ⟨a, ⟨ha, rfl⟩, rfl⟩ := hA; exact ha
+ · obtain ⟨b, ⟨hb, rfl⟩, rfl⟩ := hB; exact hb
+ rw [Prod.ext_iff] at he
+ specialize hG (mem_image.mpr ⟨a, ha, rfl⟩) (mem_image.mpr ⟨b, hb, rfl⟩) he.1
+ specialize hH _ _ he.2
+ all_goals try simp_rw [mem_image, mem_filter]
+ exacts [⟨a, ⟨ha, hG.1⟩, rfl⟩, ⟨b, ⟨hb, hG.2⟩, rfl⟩, ⟨Prod.ext hG.1 hH.1, Prod.ext hG.2 hH.2⟩]
+
+@[to_additive] instance {ι} (G : ι → Type*) [∀ i, Mul (G i)] [∀ i, UniqueProds (G i)] :
+ UniqueProds (∀ i, G i) where
+ uniqueMul_of_nonempty {A} := by
+ classical
+ let _ := Finset.isWellFounded_ssubset (α := ∀ i, G i) -- why need this?
+ apply IsWellFounded.induction (· ⊂ ·) A; intro A ihA B hA
+ apply IsWellFounded.induction (· ⊂ ·) B; intro B ihB hB
+ obtain hc | ⟨i, hc⟩ : (A.card ≤ 1 ∧ B.card ≤ 1) ∨
+ ∃ i, (∃ a1 ∈ A, ∃ a2 ∈ A, a1 i ≠ a2 i) ∨ (∃ b1 ∈ B, ∃ b2 ∈ B, b1 i ≠ b2 i)
+ · obtain hA1 | h1A := le_or_lt A.card 1
+ · obtain hB1 | h1B := le_or_lt B.card 1
+ · exact Or.inl ⟨hA1, hB1⟩
+ obtain ⟨b1, h1, b2, h2, hne⟩ := Finset.one_lt_card.mp h1B
+ obtain ⟨i, hne⟩ := Function.ne_iff.mp hne
+ exact Or.inr ⟨i, Or.inr ⟨b1, h1, b2, h2, hne⟩⟩
+ obtain ⟨a1, h1, a2, h2, hne⟩ := Finset.one_lt_card.mp h1A
+ obtain ⟨i, hne⟩ := Function.ne_iff.mp hne
+ exact Or.inr ⟨i, Or.inl ⟨a1, h1, a2, h2, hne⟩⟩
+ · obtain ⟨a0, ha0⟩ := hA; obtain ⟨b0, hb0⟩ := hB
+ simp_rw [Finset.card_le_one_iff] at hc
+ exact ⟨a0, ha0, b0, hb0, fun a b ha hb _ => ⟨hc.1 ha ha0, hc.2 hb hb0⟩⟩
+ obtain ⟨ai, hA, bi, hB, hi⟩ := uniqueMul_of_nonempty (hA.image (· i)) (hB.image (· i))
+ rw [mem_image, ← filter_nonempty_iff] at hA hB
+ let A' := A.filter (· i = ai); let B' := B.filter (· i = bi)
+ obtain ⟨a0, ha0, b0, hb0, hu⟩ : ∃ a0 ∈ A', ∃ b0 ∈ B', UniqueMul A' B' a0 b0
+ · rcases hc with ⟨a1, h1, a2, h2, hne⟩ | ⟨b1, h1, b2, h2, hne⟩
+ · refine ihA _ ⟨A.filter_subset _, fun h => ?_⟩ hA hB
+ obtain rfl | hai := eq_or_ne (a1 i) ai
+ exacts [hne (mem_filter.mp <| h h2).2.symm, hai (mem_filter.mp <| h h1).2]
+ by_cases hA' : A' = A
+ · rw [hA']; refine ihB _ ⟨B.filter_subset _, fun h => ?_⟩ hB
+ obtain rfl | hbi := eq_or_ne (b1 i) bi
+ exacts [hne (mem_filter.mp <| h h2).2.symm, hbi (mem_filter.mp <| h h1).2]
+ exact ihA A' ((A.filter_subset _).ssubset_of_ne hA') hA hB
+ rw [mem_filter] at ha0 hb0
+ refine ⟨a0, ha0.1, b0, hb0.1, fun a b ha hb he => ?_⟩
+ specialize hi (mem_image_of_mem _ ha) (mem_image_of_mem _ hb) ?_
+ · refine (congr_arg (· i) he).trans ?_; rw [← ha0.2, ← hb0.2]; rfl
+ exact hu (mem_filter.mpr ⟨ha, hi.1⟩) (mem_filter.mpr ⟨hb, hi.2⟩) he
end UniqueProds
+
+instance {ι} (G : ι → Type*) [∀ i, AddZeroClass (G i)] [∀ i, UniqueSums (G i)] :
+ UniqueSums (Π₀ i, G i) :=
+ UniqueSums.addHom_image_of_injective
+ DFinsupp.coeFnAddMonoidHom.toAddHom FunLike.coe_injective inferInstance
+
+instance {ι G} [AddZeroClass G] [UniqueSums G] : UniqueSums (ι →₀ G) :=
+ UniqueSums.addHom_image_of_injective
+ Finsupp.coeFnAddHom.toAddHom FunLike.coe_injective inferInstance
@@ -62,6 +62,10 @@ namespace UniqueMul
variable {G H : Type*} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
+@[to_additive (attr := nontriviality, simp)]
+theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 := by simp [UniqueMul]
+
+@[to_additive]
theorem mt {G} [Mul G] {A B : Finset G} {a0 b0 : G} (h : UniqueMul A B a0 b0) :
∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k ↦ by
contrapose! k
@@ -165,6 +169,37 @@ theorem mulHom_map_iff (f : G ↪ H) (mul : ∀ x y, f (x * y) = f x * f y) :
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
#align unique_add.add_hom_map_iff UniqueAdd.addHom_map_iff
+section Opposites
+open Finset MulOpposite
+
+@[to_additive]
+theorem of_mulOpposite
+ (h : UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0)) :
+ UniqueMul A B a0 b0 := by
+ intros a b aA bB ab
+ have := h (mem_map_of_mem _ bB) (mem_map_of_mem _ aA) (by simpa using congr_arg op ab)
+ simpa [and_comm] using this
+
+@[to_additive]
+theorem to_mulOpposite (h : UniqueMul A B a0 b0) :
+ UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) := by
+ refine of_mulOpposite (G := MulOpposite G) <| fun a b ha hb hab ↦ ?_
+ simp only [mem_map, Function.Embedding.coeFn_mk, exists_exists_and_eq_and] at ha hb
+ rcases ha with ⟨a, ha, rfl⟩
+ rcases hb with ⟨b, hb, rfl⟩
+ rw [op_inj, op_inj, op_inj, op_inj]
+ apply h ha hb ?_
+ apply_fun op ∘ op using op_injective.comp op_injective
+ exact hab
+
+@[to_additive]
+theorem iff_mulOpposite :
+ UniqueMul (B.map ⟨_, op_injective⟩) (A.map ⟨_, op_injective⟩) (op b0) (op a0) ↔
+ UniqueMul A B a0 b0 :=
+⟨of_mulOpposite, to_mulOpposite⟩
+
+end Opposites
+
end UniqueMul
/-- Let `G` be a Type with addition. `UniqueSums G` asserts that any two non-empty
@@ -212,8 +247,43 @@ is 'very monotone', then `A` also has `UniqueSums`."]
instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
[ContravariantClass A A (· * ·) (· ≤ ·)] : UniqueProds A where
- uniqueMul_of_nonempty {A} {B} hA hB :=
- ⟨_, A.max'_mem ‹_›, _, B.max'_mem ‹_›, fun a b ha hb ↦
- (mul_eq_mul_iff_eq_and_eq (Finset.le_max' _ _ ‹_›) (Finset.le_max' _ _ ‹_›)).mp⟩
+ uniqueMul_of_nonempty {A B} hA hB :=
+ ⟨_, A.max'_mem ‹_›, _, B.max'_mem ‹_›, fun a b ha hb ↦
+ (mul_eq_mul_iff_eq_and_eq (Finset.le_max' _ _ ‹_›) (Finset.le_max' _ _ ‹_›)).mp⟩
#align covariants.to_unique_prods Covariants.to_uniqueProds
#align covariants.to_unique_sums Covariants.to_uniqueSums
+
+namespace UniqueProds
+
+@[to_additive (attr := nontriviality, simp)]
+theorem of_subsingleton {G : Type*} [Mul G] [Subsingleton G] : UniqueProds G where
+ uniqueMul_of_nonempty {A B} | ⟨a, hA⟩, ⟨b, hB⟩ => ⟨a, hA, b, hB, by simp⟩
+
+open Finset MulOpposite in
+@[to_additive]
+theorem of_mulOpposite (G : Type*) [Mul G] (h : UniqueProds Gᵐᵒᵖ) :
+ UniqueProds G :=
+ ⟨fun hA hB =>
+ let f : G ↪ Gᵐᵒᵖ := ⟨op, op_injective⟩
+ let ⟨y, yB, x, xA, hxy⟩ := h.uniqueMul_of_nonempty (hB.map (f := f)) (hA.map (f := f))
+ ⟨unop x, (mem_map' _).mp xA, unop y, (mem_map' _).mp yB, hxy.of_mulOpposite⟩⟩
+
+open MulOpposite in
+@[to_additive (attr := simp)]
+theorem iff_mulOpposite (G : Type*) [Mul G] :
+ UniqueProds Gᵐᵒᵖ ↔ UniqueProds G := by
+ refine ⟨of_mulOpposite G, fun h ↦ of_mulOpposite (Gᵐᵒᵖ) ⟨fun {A B} hA hB ↦ ?_⟩⟩
+ classical
+ let f : Gᵐᵒᵖᵐᵒᵖ ↪ G := ⟨_, unop_injective.comp unop_injective⟩
+ obtain ⟨a0, ha0, b0, hb0, d⟩ :=
+ h.uniqueMul_of_nonempty (Finset.Nonempty.map (f := f) hA) (Finset.Nonempty.map (f := f) hB)
+ simp only [Finset.mem_map, Function.Embedding.coeFn_mk, Function.comp_apply] at ha0 hb0
+ rcases ha0 with ⟨a0, ha0, rfl⟩
+ rcases hb0 with ⟨b0, hb0, rfl⟩
+ refine ⟨a0, ha0, b0, hb0, ?_⟩
+ apply (UniqueMul.mulHom_map_iff (H := G) (⟨_, unop_injective.comp unop_injective⟩) ?_).mp
+ · simp only [Function.Embedding.coeFn_mk, Function.comp_apply]
+ convert d
+ · simp only [Function.Embedding.coeFn_mk, Function.comp_apply, unop_mul, implies_true]
+
+end UniqueProds
4 files have major changes:
Algebra/CovariantAndContravariant.lean
contravariant_le_iff_contravariant_lt_and_eq
.covariantClass_le_of_lt
generalizing and replacing Mul.to_covariantClass_left/right
in Algebra/Order/Monoid/Defs.leanCommSemigroup
by IsSymmOp N N mu
and replace CancelSemigroup
by IsMulCancel
, removing superfluous associativity assumption.covariant_lt_of_covariant_le_of_contravariant_eq
and contravariant_le_of_contravariant_eq_and_lt
that could replace eight instances when appropriate refactoring is in place.Algebra/Order/Monoid/Lemmas.lean
mul_eq_mul_iff_eq_and_eq
and remove the less general Left/Right.mul_eq_mul_iff_eq_and_eq
.mul_le_mul_iff_of_ge
.min_le_max_of_mul_le_mul
.min_lt_max_of_mul_lt_mul
here from Algebra/GroupPower/Order.lean.CommSemigroup
by IsSymmOp
.Algebra/Order/Monoid/Basic.lean
eq_and_eq_of_le_of_le_of_mul_le
as it's just one direction of mul_le_mul_iff_of_ge
but with more assumptions.Algebra/Order/Ring/Lemmas.lean
mul_eq_mul_iff_eq_and_eq_of_pos
Changes to Algebra/Group/UniqueProds.lean and Algebra/MonoidAlgebra/NoZeroDivisors.lean are in declarations that will be removed by #6723.
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -213,7 +213,7 @@ instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
[CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
[ContravariantClass A A (· * ·) (· ≤ ·)] : UniqueProds A where
uniqueMul_of_nonempty {A} {B} hA hB :=
- ⟨_, A.min'_mem ‹_›, _, B.min'_mem ‹_›, fun a b ha hb ab ↦
- eq_and_eq_of_le_of_le_of_mul_le (Finset.min'_le _ _ ‹_›) (Finset.min'_le _ _ ‹_›) ab.le⟩
+ ⟨_, A.max'_mem ‹_›, _, B.max'_mem ‹_›, fun a b ha hb ↦
+ (mul_eq_mul_iff_eq_and_eq (Finset.le_max' _ _ ‹_›) (Finset.le_max' _ _ ‹_›)).mp⟩
#align covariants.to_unique_prods Covariants.to_uniqueProds
#align covariants.to_unique_sums Covariants.to_uniqueSums
[uU]niqueProds →[uU]niqueSums
(#6751)
This PR adds to_additive
support to convert
UniqueProds
to UniqueSums
anduniqueProds
to uniqueSums
.This is just the dictionary support, plus the removal of two, now correctly guessed, to_additive
names.
@@ -187,7 +187,7 @@ class UniqueProds (G) [Mul G] : Prop where
∀ {A B : Finset G} (_ : A.Nonempty) (_ : B.Nonempty), ∃ a0 ∈ A, ∃ b0 ∈ B, UniqueMul A B a0 b0
#align unique_prods UniqueProds
-attribute [to_additive UniqueSums] UniqueProds
+attribute [to_additive] UniqueProds
namespace Multiplicative
@@ -206,7 +206,7 @@ end Additive
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `UniqueProds`. -/
-@[to_additive Covariants.to_uniqueSums
+@[to_additive
"This instance asserts that if `A` has an addition, a linear order, and addition
is 'very monotone', then `A` also has `UniqueSums`."]
instance (priority := 100) Covariants.to_uniqueProds {A} [Mul A] [LinearOrder A]
@@ -124,8 +124,7 @@ theorem mulHom_preimage (f : G →ₙ* H) (hf : Function.Injective f) (a0 b0 : G
UniqueMul (A.preimage f (Set.injOn_of_injective hf _))
(B.preimage f (Set.injOn_of_injective hf _)) a0 b0 := by
intro a b ha hb ab
- rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
+ simp only [← hf.eq_iff, map_mul] at ab ⊢
exact u (Finset.mem_preimage.mp ha) (Finset.mem_preimage.mp hb) ab
#align unique_mul.mul_hom_preimage UniqueMul.mulHom_preimage
#align unique_add.add_hom_preimage UniqueAdd.addHom_preimage
@@ -139,17 +138,14 @@ See `UniqueMul.mulHom_map_iff` for a version with swapped bundling. -/
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 := by
- refine' ⟨fun h ↦ _, fun h ↦ _⟩
- · intro a b ha hb ab
- rw [← hf.eq_iff, ← hf.eq_iff]
- rw [← hf.eq_iff, map_mul, map_mul] at ab
- exact h (Finset.mem_image.mpr ⟨_, ha, rfl⟩) (Finset.mem_image.mpr ⟨_, hb, rfl⟩) ab
- · intro a b aA bB ab
- obtain ⟨a, ha, rfl⟩ : ∃ a' ∈ A, f a' = a := Finset.mem_image.mp aA
- obtain ⟨b, hb, rfl⟩ : ∃ b' ∈ B, f b' = b := Finset.mem_image.mp bB
- rw [hf.eq_iff, hf.eq_iff]
- rw [← map_mul, ← map_mul, hf.eq_iff] at ab
- exact h ha hb ab
+ simp_rw [UniqueMul, Finset.mem_image]
+ refine' ⟨fun h a b ha hb ab ↦ _, fun h ↦ _⟩
+ · rw [← hf.eq_iff, map_mul, map_mul] at ab
+ have := h ⟨a, ha, rfl⟩ ⟨b, hb, rfl⟩ ab
+ exact ⟨hf this.1, hf this.2⟩
+ · rintro _ _ ⟨a, aA, rfl⟩ ⟨b, bB, rfl⟩ ab
+ simp only [← map_mul, hf.eq_iff] at ab ⊢
+ exact h aA bB ab
#align unique_mul.mul_hom_image_iff UniqueMul.mulHom_image_iff
#align unique_add.add_hom_image_iff UniqueAdd.addHom_image_iff
@@ -196,22 +192,14 @@ attribute [to_additive UniqueSums] UniqueProds
namespace Multiplicative
instance {M} [Add M] [UniqueSums M] : UniqueProds (Multiplicative M) where
- uniqueMul_of_nonempty {A} {B} hA hB := by
- let A' : Finset M := A
- have hA' : A'.Nonempty := hA
- obtain ⟨a0, hA0, b0, hB0, J⟩ := UniqueSums.uniqueAdd_of_nonempty hA' hB
- exact ⟨ofAdd a0, hA0, ofAdd b0, hB0, fun a b aA bB H ↦ J aA bB H⟩
+ uniqueMul_of_nonempty := UniqueSums.uniqueAdd_of_nonempty (G := M)
end Multiplicative
namespace Additive
instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M) where
- uniqueAdd_of_nonempty {A} {B} hA hB := by
- let A' : Finset M := A
- have hA' : A'.Nonempty := hA
- obtain ⟨a0, hA0, b0, hB0, J⟩ := UniqueProds.uniqueMul_of_nonempty hA' hB
- exact ⟨ofMul a0, hA0, ofMul b0, hB0, fun a b aA bB H ↦ J aA bB H⟩
+ uniqueAdd_of_nonempty := UniqueProds.uniqueMul_of_nonempty (G := M)
end Additive
A simple update of the docs for UniqueProds/Sums
. I also added a paragraph explaining the relationship between UniqueProds/Sums
and (Add)MonoidAlgebras
.
@@ -14,23 +14,35 @@ A group `G` has *unique products* if for any two non-empty finite subsets `A, B
element `g ∈ A * B` that can be written uniquely as a product of an element of `A` and an element
of `B`. We call the formalization this property `UniqueProds`. Since the condition requires no
property of the group operation, we define it for a Type simply satisfying `Mul`. We also
-introduce the analogous "additive" companion, `UniqueSums` and link the two so that `to_additive`
+introduce the analogous "additive" companion, `UniqueSums`, and link the two so that `to_additive`
converts `UniqueProds` into `UniqueSums`.
+A common way of *proving* that a group satisfies the `UniqueProds/Sums` property is by assuming
+the existence of some kind of ordering on the group that is well-behaved with respect to the
+group operation and showing that minima/maxima are the "unique products/sums".
+However, the order is just a convenience and is not part of the `UniqueProds/Sums` setup.
+
Here you can see several examples of Types that have `UniqueSums/Prods`
-(`infer_instance` uses `Covariants.to_uniqueProds` and `Covariants.to_uniqueSums`).
+(`inferInstance` uses `Covariant.to_uniqueProds_left` and `Covariant.to_uniqueSums_left`).
```lean
import Mathlib.Data.Real.Basic
import Mathlib.Data.PNat.Basic
import Mathlib.Algebra.Group.UniqueProds
-example : UniqueSums ℕ := by infer_instance
-example : UniqueSums ℕ+ := by infer_instance
-example : UniqueSums ℤ := by infer_instance
-example : UniqueSums ℚ := by infer_instance
-example : UniqueSums ℝ := by infer_instance
-example : UniqueProds ℕ+ := by infer_instance
+example : UniqueSums ℕ := inferInstance
+example : UniqueSums ℕ+ := inferInstance
+example : UniqueSums ℤ := inferInstance
+example : UniqueSums ℚ := inferInstance
+example : UniqueSums ℝ := inferInstance
+example : UniqueProds ℕ+ := inferInstance
```
+
+## Use in `(Add)MonoidAlgebra`s
+
+`UniqueProds/Sums` allow to decouple certain arguments about `(Add)MonoidAlgebra`s into an argument
+about the grading type and then a generic statement of the form "look at the coefficient of the
+'unique product/sum'".
+The file `Algebra/MonoidAlgebra/NoZeroDivisors` contains several examples of this use.
-/
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -48,7 +48,7 @@ def UniqueMul {G} [Mul G] (A B : Finset G) (a0 b0 : G) : Prop :=
namespace UniqueMul
-variable {G H : Type _} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
+variable {G H : Type*} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G}
theorem mt {G} [Mul G] {A B : Finset G} {a0 b0 : G} (h : UniqueMul A B a0 b0) :
∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k ↦ by
eq_and_eq_of_le_of_le_of_mul_le
earlier (#6483)
This move was suggested in #6220. In fact, the lemma is a general fact about an inequality involving multiplications and did not really belong in the file where it was.
Affected files:
Algebra.Group.UniqueProds
Algebra.Order.Monoid.Basic
@@ -203,19 +203,6 @@ instance {M} [Mul M] [UniqueProds M] : UniqueSums (Additive M) where
end Additive
-@[to_additive]
-theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
- [CovariantClass A A (· * ·) (· ≤ ·)] [CovariantClass A A (Function.swap (· * ·)) (· < ·)]
- [ContravariantClass A A (· * ·) (· ≤ ·)] {a b a0 b0 : A} (ha : a0 ≤ a) (hb : b0 ≤ b)
- (ab : a * b ≤ a0 * b0) : a = a0 ∧ b = b0 := by
- haveI := Mul.to_covariantClass_right A
- have ha' : ¬a0 * b0 < a * b → ¬a0 < a := mt fun h ↦ mul_lt_mul_of_lt_of_le h hb
- have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h ↦ mul_lt_mul_of_le_of_lt ha h
- push_neg at ha' hb'
- exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
-#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
-#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
-
-- see Note [lower instance priority]
/-- This instance asserts that if `A` has a multiplication, a linear order, and multiplication
is 'very monotone', then `A` also has `UniqueProds`. -/
@@ -18,7 +18,7 @@ introduce the analogous "additive" companion, `UniqueSums` and link the two so t
converts `UniqueProds` into `UniqueSums`.
Here you can see several examples of Types that have `UniqueSums/Prods`
-(`infer_instance` uses `covariants.to_uniqueProds` and `covariants.to_uniqueSums`).
+(`infer_instance` uses `Covariants.to_uniqueProds` and `Covariants.to_uniqueSums`).
```lean
import Mathlib.Data.Real.Basic
import Mathlib.Data.PNat.Basic
@@ -2,14 +2,11 @@
Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa
-
-! This file was ported from Lean 3 source module algebra.group.unique_prods
-! leanprover-community/mathlib commit d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Data.Finset.Preimage
+#align_import algebra.group.unique_prods from "leanprover-community/mathlib"@"d6fad0e5bf2d6f48da9175d25c3dc5706b3834ce"
+
/-!
# Unique products and related notions
@@ -11,7 +11,7 @@ Authors: Damiano Testa
import Mathlib.Data.Finset.Preimage
/-!
-# Unique products and related notions
+# Unique products and related notions
A group `G` has *unique products* if for any two non-empty finite subsets `A, B ⊂ G`, there is an
element `g ∈ A * B` that can be written uniquely as a product of an element of `A` and an element
at
and goals (#5387)
Changes are of the form
some_tactic at h⊢
-> some_tactic at h ⊢
some_tactic at h
-> some_tactic at h
@@ -214,7 +214,7 @@ theorem eq_and_eq_of_le_of_le_of_mul_le {A} [Mul A] [LinearOrder A]
haveI := Mul.to_covariantClass_right A
have ha' : ¬a0 * b0 < a * b → ¬a0 < a := mt fun h ↦ mul_lt_mul_of_lt_of_le h hb
have hb' : ¬a0 * b0 < a * b → ¬b0 < b := mt fun h ↦ mul_lt_mul_of_le_of_lt ha h
- push_neg at ha' hb'
+ push_neg at ha' hb'
exact ⟨ha.antisymm' (ha' ab), hb.antisymm' (hb' ab)⟩
#align eq_and_eq_of_le_of_le_of_mul_le eq_and_eq_of_le_of_le_of_mul_le
#align eq_and_eq_of_le_of_le_of_add_le eq_and_eq_of_le_of_le_of_add_le
@@ -84,7 +84,7 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
-- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
@[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 :=
+ UniqueMul A B a0 b0 ↔ ∃! (ab : _) (_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = a0 * b0 :=
⟨fun _ ↦ ⟨(a0, b0), ⟨Finset.mem_product.mpr ⟨aA, bB⟩, rfl, by simp⟩, by simpa⟩,
fun h ↦ h.elim₂
(by
@@ -99,7 +99,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
@[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 :=
+ ∃ g : G, ∃! (ab : _) (_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = g :=
⟨fun ⟨a0, b0, hA, hB, h⟩ ↦ ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ ↦ by
have h' := h
rcases h' with ⟨⟨a, b⟩, ⟨hab, rfl, -⟩, -⟩
SProd
to implement overloaded notation · ×ˢ ·
(#4200)
Currently, the following notations are changed from · ×ˢ ·
because Lean 4 can't deal with ambiguous notations.
| Definition | Notation |
| :
Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
@@ -82,10 +82,9 @@ theorem set_subsingleton (A B : Finset G) (a0 b0 : G) (h : UniqueMul A B a0 b0)
-- Porting note: mathport warning: expanding binder collection
-- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
--- Porting note: replaced `xˢ` by `xᶠ`
@[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 :=
+ UniqueMul A B a0 b0 ↔ ∃! (ab : _)(_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = a0 * b0 :=
⟨fun _ ↦ ⟨(a0, b0), ⟨Finset.mem_product.mpr ⟨aA, bB⟩, rfl, by simp⟩, by simpa⟩,
fun h ↦ h.elim₂
(by
@@ -97,11 +96,10 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
-- Porting note: mathport warning: expanding binder collection
-- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/
--- Porting note: replaced `xˢ` by `xᶠ`
@[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 :=
+ ∃ g : G, ∃! (ab : _)(_ : ab ∈ A ×ˢ B), ab.1 * ab.2 = g :=
⟨fun ⟨a0, b0, hA, hB, h⟩ ↦ ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ ↦ by
have h' := h
rcases h' with ⟨⟨a, b⟩, ⟨hab, rfl, -⟩, -⟩
by
s! (#3825)
This PR puts, with one exception, every single remaining by
that lies all by itself on its own line to the previous line, thus matching the current behaviour of start-port.sh
. The exception is when the by
begins the second or later argument to a tuple or anonymous constructor; see https://github.com/leanprover-community/mathlib4/pull/3825#discussion_r1186702599.
Essentially this is s/\n *by$/ by/g
, but with manual editing to satisfy the linter's max-100-char-line requirement. The Python style linter is also modified to catch these "isolated by
s".
@@ -102,8 +102,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) :
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 :=
- ⟨fun ⟨a0, b0, hA, hB, h⟩ ↦ ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ ↦
- by
+ ⟨fun ⟨a0, b0, hA, hB, h⟩ ↦ ⟨_, (iff_existsUnique hA hB).mp h⟩, fun ⟨g, h⟩ ↦ by
have h' := h
rcases h' with ⟨⟨a, b⟩, ⟨hab, rfl, -⟩, -⟩
cases' Finset.mem_product.mp hab with ha hb
congr!
and convert
(#2606)
congr!
, convert
, and convert_to
to control parts of the congruence algorithm, in particular transparency settings when applying congruence lemmas.congr!
now applies congruence lemmas with reducible transparency by default. This prevents it from unfolding definitions when applying congruence lemmas. It also now tries both the LHS-biased and RHS-biased simp congruence lemmas, with a configuration option to set which it should try first.HEq
congruence lemma generator that gives each hypothesis access to the proofs of previous hypotheses. This means that if you have an equality ⊢ ⟨a, x⟩ = ⟨b, y⟩
of sigma types, congr!
turns this into goals ⊢ a = b
and ⊢ a = b → HEq x y
(note that congr!
will also auto-introduce a = b
for you in the second goal). This congruence lemma generator applies to more cases than the simp congruence lemma generator does.congr!
(and hence convert
) are more careful about applying lemmas that don't force definitions to unfold. There were a number of cases in mathlib where the implementation of congr
was being abused to unfold definitions.set_option trace.congr! true
you can see what congr!
sees when it is deciding on congruence lemmas.convert_to
to do using 1
when there is no using
clause, to match its documentation.Note that congr!
is more capable than congr
at finding a way to equate left-hand sides and right-hand sides, so you will frequently need to limit its depth with a using
clause. However, there is also a new heuristic to prevent considering unlikely-to-be-provable type equalities (controlled by the typeEqs
option), which can help limit the depth automatically.
There is also a predefined configuration that you can invoke with, for example, convert (config := .unfoldSameFun) h
, that causes it to behave more like congr
, including using default transparency when unfolding.
@@ -156,7 +156,8 @@ See `UniqueMul.mulHom_image_iff` for a version with swapped bundling. -/
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 := by
- classical convert @mulHom_image_iff G H _ _ A B a0 b0 _ ⟨f, mul⟩ f.2 <;>
+ classical
+ convert @mulHom_image_iff G H _ _ A B a0 b0 _ ⟨f, mul⟩ f.2 using 2 <;>
· ext
simp only [Finset.mem_map, MulHom.coe_mk, Finset.mem_image]
#align unique_mul.mul_hom_map_iff UniqueMul.mulHom_map_iff
The unported dependencies are