Skip to content

Commit c143082

Browse files
committed
feat: port Counterexamples.CanonicallyOrderedCommSemiringTwoMul (leanprover-community#5162)
1 parent d063ef5 commit c143082

File tree

2 files changed

+280
-0
lines changed

2 files changed

+280
-0
lines changed

Counterexamples.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Counterexamples.CanonicallyOrderedCommSemiringTwoMul
12
import Counterexamples.CharPZeroNeCharZero
23
import Counterexamples.Cyclotomic105
34
import Counterexamples.DirectSumIsInternal
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/-
2+
Copyright (c) 2021 Damiano Testa. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Damiano Testa
5+
6+
! This file was ported from Lean 3 source module canonically_ordered_comm_semiring_two_mul
7+
! leanprover-community/mathlib commit 328375597f2c0dd00522d9c2e5a33b6a6128feeb
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.ZMod.Basic
12+
import Mathlib.RingTheory.Subsemiring.Basic
13+
import Mathlib.Algebra.Order.Monoid.Basic
14+
15+
/-!
16+
17+
A `CanonicallyOrderedCommSemiring` with two different elements `a` and `b` such that
18+
`a ≠ b` and `2 * a = 2 * b`. Thus, multiplication by a fixed non-zero element of a canonically
19+
ordered semiring need not be injective. In particular, multiplying by a strictly positive element
20+
need not be strictly monotone.
21+
22+
Recall that a `CanonicallyOrderedCommSemiring` is a commutative semiring with a partial ordering
23+
that is "canonical" in the sense that the inequality `a ≤ b` holds if and only if there is a `c`
24+
such that `a + c = b`. There are several compatibility conditions among addition/multiplication
25+
and the order relation. The point of the counterexample is to show that monotonicity of
26+
multiplication cannot be strengthened to **strict** monotonicity.
27+
28+
Reference:
29+
https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/canonically_ordered.20pathology
30+
-/
31+
32+
33+
set_option linter.uppercaseLean3 false
34+
35+
namespace Counterexample
36+
37+
namespace FromBhavik
38+
39+
/-- Bhavik Mehta's example. There are only the initial definitions, but no proofs. The Type
40+
`K` is a canonically ordered commutative semiring with the property that `2 * (1/2) ≤ 2 * 1`, even
41+
though it is not true that `1/2 ≤ 1`, since `1/2` and `1` are not comparable. -/
42+
def K : Type :=
43+
Subsemiring.closure ({1.5} : Set ℚ)
44+
deriving CommSemiring
45+
#align counterexample.from_Bhavik.K Counterexample.FromBhavik.K
46+
47+
instance : Coe K ℚ :=
48+
fun x => x.1
49+
50+
instance inhabitedK : Inhabited K :=
51+
0
52+
#align counterexample.from_Bhavik.inhabited_K Counterexample.FromBhavik.inhabitedK
53+
54+
instance : Preorder K where
55+
le x y := x = y ∨ (x : ℚ) + 1 ≤ (y : ℚ)
56+
le_refl x := Or.inl rfl
57+
le_trans x y z xy yz := by
58+
rcases xy with (rfl | xy); · apply yz
59+
rcases yz with (rfl | yz); · right; apply xy
60+
right
61+
exact xy.trans (le_trans ((le_add_iff_nonneg_right _).mpr zero_le_one) yz)
62+
63+
end FromBhavik
64+
65+
theorem mem_zmod_2 (a : ZMod 2) : a = 0 ∨ a = 1 := by
66+
rcases a with ⟨_ | _, _ | _ | _ | _⟩
67+
· exact Or.inl rfl
68+
· exact Or.inr rfl
69+
#align counterexample.mem_zmod_2 Counterexample.mem_zmod_2
70+
71+
theorem add_self_zmod_2 (a : ZMod 2) : a + a = 0 := by rcases mem_zmod_2 a with (rfl | rfl) <;> rfl
72+
#align counterexample.add_self_zmod_2 Counterexample.add_self_zmod_2
73+
74+
namespace Nxzmod2
75+
76+
variable {a b : ℕ × ZMod 2}
77+
78+
/-- The preorder relation on `ℕ × ℤ/2ℤ` where we only compare the first coordinate,
79+
except that we leave incomparable each pair of elements with the same first component.
80+
For instance, `∀ α, β ∈ ℤ/2ℤ`, the inequality `(1,α) ≤ (2,β)` holds,
81+
whereas, `∀ n ∈ ℤ`, the elements `(n,0)` and `(n,1)` are incomparable. -/
82+
instance preN2 : PartialOrder (ℕ × ZMod 2) where
83+
le x y := x = y ∨ x.1 < y.1
84+
le_refl a := Or.inl rfl
85+
le_trans x y z xy yz := by
86+
rcases xy with (rfl | xy)
87+
· exact yz
88+
· rcases yz with (rfl | yz)
89+
· exact Or.inr xy
90+
· exact Or.inr (xy.trans yz)
91+
le_antisymm := by
92+
intro a b ab ba
93+
cases' ab with ab ab
94+
· exact ab
95+
· cases' ba with ba ba
96+
· exact ba.symm
97+
· exact (Nat.lt_asymm ab ba).elim
98+
#align counterexample.Nxzmod_2.preN2 Counterexample.Nxzmod2.preN2
99+
100+
instance csrN2 : CommSemiring (ℕ × ZMod 2) := by infer_instance
101+
#align counterexample.Nxzmod_2.csrN2 Counterexample.Nxzmod2.csrN2
102+
103+
instance csrN21 : AddCancelCommMonoid (ℕ × ZMod 2) :=
104+
{ Nxzmod2.csrN2 with add_left_cancel := fun a _ _ h => (add_right_inj a).mp h }
105+
#align counterexample.Nxzmod_2.csrN2_1 Counterexample.Nxzmod2.csrN21
106+
107+
/-- A strict inequality forces the first components to be different. -/
108+
@[simp]
109+
theorem lt_def : a < b ↔ a.1 < b.1 := by
110+
refine' ⟨fun h => _, fun h => _⟩
111+
· rcases h with ⟨rfl | a1, h1⟩
112+
· exact (not_or.mp h1).1.elim rfl
113+
· exact a1
114+
refine' ⟨Or.inr h, not_or.mpr ⟨fun k => _, not_lt.mpr h.le⟩⟩
115+
rw [k] at h
116+
exact Nat.lt_asymm h h
117+
#align counterexample.Nxzmod_2.lt_def Counterexample.Nxzmod2.lt_def
118+
119+
theorem add_left_cancel : ∀ a b c : ℕ × ZMod 2, a + b = a + c → b = c := fun a _ _ h =>
120+
(add_right_inj a).mp h
121+
#align counterexample.Nxzmod_2.add_left_cancel Counterexample.Nxzmod2.add_left_cancel
122+
123+
theorem add_le_add_left : ∀ a b : ℕ × ZMod 2, a ≤ b → ∀ c : ℕ × ZMod 2, c + a ≤ c + b := by
124+
rintro a b (rfl | ab) c
125+
· rfl
126+
· exact Or.inr (by simpa)
127+
#align counterexample.Nxzmod_2.add_le_add_left Counterexample.Nxzmod2.add_le_add_left
128+
129+
theorem le_of_add_le_add_left : ∀ a b c : ℕ × ZMod 2, a + b ≤ a + c → b ≤ c := by
130+
rintro a b c (bc | bc)
131+
· exact le_of_eq ((add_right_inj a).mp bc)
132+
· exact Or.inr (by simpa using bc)
133+
#align counterexample.Nxzmod_2.le_of_add_le_add_left Counterexample.Nxzmod2.le_of_add_le_add_left
134+
135+
instance : ZeroLEOneClass (ℕ × ZMod 2) :=
136+
by dsimp only [LE.le]; decide⟩
137+
138+
theorem mul_lt_mul_of_pos_left : ∀ a b c : ℕ × ZMod 2, a < b → 0 < c → c * a < c * b :=
139+
fun _ _ _ ab c0 => lt_def.mpr ((mul_lt_mul_left (lt_def.mp c0)).mpr (lt_def.mp ab))
140+
#align counterexample.Nxzmod_2.mul_lt_mul_of_pos_left Counterexample.Nxzmod2.mul_lt_mul_of_pos_left
141+
142+
theorem mul_lt_mul_of_pos_right : ∀ a b c : ℕ × ZMod 2, a < b → 0 < c → a * c < b * c :=
143+
fun _ _ _ ab c0 => lt_def.mpr ((mul_lt_mul_right (lt_def.mp c0)).mpr (lt_def.mp ab))
144+
#align counterexample.Nxzmod_2.mul_lt_mul_of_pos_right Counterexample.Nxzmod2.mul_lt_mul_of_pos_right
145+
146+
instance socsN2 : StrictOrderedCommSemiring (ℕ × ZMod 2) :=
147+
{ Nxzmod2.csrN21, (inferInstance : PartialOrder (ℕ × ZMod 2)),
148+
(inferInstance : CommSemiring (ℕ × ZMod 2)),
149+
pullback_nonzero Prod.fst Prod.fst_zero
150+
Prod.fst_one with
151+
add_le_add_left := add_le_add_left
152+
le_of_add_le_add_left := le_of_add_le_add_left
153+
zero_le_one := zero_le_one
154+
mul_lt_mul_of_pos_left := mul_lt_mul_of_pos_left
155+
mul_lt_mul_of_pos_right := mul_lt_mul_of_pos_right }
156+
#align counterexample.Nxzmod_2.socsN2 Counterexample.Nxzmod2.socsN2
157+
158+
end Nxzmod2
159+
160+
namespace ExL
161+
162+
open Nxzmod2 Subtype
163+
164+
/-- Initially, `L` was defined as the subsemiring closure of `(1,0)`. -/
165+
def L : Type :=
166+
{ l : ℕ × ZMod 2 // l ≠ (0, 1) }
167+
#align counterexample.ex_L.L Counterexample.ExL.L
168+
169+
theorem add_L {a b : ℕ × ZMod 2} (ha : a ≠ (0, 1)) (hb : b ≠ (0, 1)) : a + b ≠ (0, 1) := by
170+
rcases a with ⟨a, a2⟩
171+
rcases b with ⟨b, b2⟩
172+
match b with
173+
| 0 =>
174+
rcases mem_zmod_2 b2 with (rfl | rfl)
175+
· simp [ha, -Prod.mk.injEq]
176+
· cases hb rfl
177+
| b + 1 =>
178+
simp [(a + b).succ_ne_zero]
179+
#align counterexample.ex_L.add_L Counterexample.ExL.add_L
180+
181+
theorem mul_L {a b : ℕ × ZMod 2} (ha : a ≠ (0, 1)) (hb : b ≠ (0, 1)) : a * b ≠ (0, 1) := by
182+
rcases a with ⟨a, a2⟩
183+
rcases b with ⟨b, b2⟩
184+
cases b
185+
· rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> simp
186+
-- while this looks like a non-terminal `simp`, it (almost) isn't: there is only one goal where
187+
-- it does not finish the proof and on that goal it asks to prove `false`
188+
exact hb rfl
189+
cases a
190+
· rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> simp
191+
-- while this looks like a non-terminal `simp`, it (almost) isn't: there is only one goal where
192+
-- it does not finish the proof and on that goal it asks to prove `false`
193+
exact ha rfl
194+
· simp [mul_ne_zero _ _, Nat.succ_ne_zero _]
195+
#align counterexample.ex_L.mul_L Counterexample.ExL.mul_L
196+
197+
/-- The subsemiring corresponding to the elements of `L`, used to transfer instances. -/
198+
def lSubsemiring : Subsemiring (ℕ × ZMod 2) where
199+
carrier := {l | l ≠ (0, 1)}
200+
zero_mem' := by decide
201+
one_mem' := by decide
202+
add_mem' := add_L
203+
mul_mem' := mul_L
204+
#align counterexample.ex_L.L_subsemiring Counterexample.ExL.lSubsemiring
205+
206+
instance : OrderedCommSemiring L :=
207+
lSubsemiring.toOrderedCommSemiring
208+
209+
instance inhabited : Inhabited L :=
210+
1
211+
#align counterexample.ex_L.inhabited Counterexample.ExL.inhabited
212+
213+
theorem bot_le : ∀ a : L, 0 ≤ a := by
214+
rintro ⟨⟨an, a2⟩, ha⟩
215+
cases an
216+
· rcases mem_zmod_2 a2 with (rfl | rfl)
217+
· rfl
218+
· exact (ha rfl).elim
219+
· refine' Or.inr _
220+
exact Nat.succ_pos _
221+
#align counterexample.ex_L.bot_le Counterexample.ExL.bot_le
222+
223+
instance orderBot : OrderBot L where
224+
bot := 0
225+
bot_le := bot_le
226+
#align counterexample.ex_L.order_bot Counterexample.ExL.orderBot
227+
228+
theorem exists_add_of_le : ∀ a b : L, a ≤ b → ∃ c, b = a + c := by
229+
rintro a ⟨b, _⟩ (⟨rfl, rfl⟩ | h)
230+
· exact ⟨0, (add_zero _).symm⟩
231+
· exact
232+
⟨⟨b - a.1, fun H => (tsub_pos_of_lt h).ne' (Prod.mk.inj_iff.1 H).1⟩,
233+
Subtype.ext <| Prod.ext (add_tsub_cancel_of_le h.le).symm (add_sub_cancel'_right _ _).symm⟩
234+
#align counterexample.ex_L.exists_add_of_le Counterexample.ExL.exists_add_of_le
235+
236+
theorem le_self_add : ∀ a b : L, a ≤ a + b := by
237+
rintro a ⟨⟨bn, b2⟩, hb⟩
238+
obtain rfl | h := Nat.eq_zero_or_pos bn
239+
· obtain rfl | rfl := mem_zmod_2 b2
240+
· exact Or.inl (Prod.ext (add_zero _).symm (add_zero _).symm)
241+
· exact (hb rfl).elim
242+
· exact Or.inr ((lt_add_iff_pos_right _).mpr h)
243+
#align counterexample.ex_L.le_self_add Counterexample.ExL.le_self_add
244+
245+
theorem eq_zero_or_eq_zero_of_mul_eq_zero : ∀ a b : L, a * b = 0 → a = 0 ∨ b = 0 := by
246+
rintro ⟨⟨a, a2⟩, ha⟩ ⟨⟨b, b2⟩, hb⟩ ab1
247+
injection ab1 with ab
248+
injection ab with abn ab2
249+
rw [mul_eq_zero] at abn
250+
rcases abn with (⟨rfl, rfl⟩ | ⟨rfl, rfl⟩)
251+
· refine' Or.inl _
252+
rcases mem_zmod_2 a2 with (rfl | rfl)
253+
· rfl
254+
· exact (ha rfl).elim
255+
· refine' Or.inr _
256+
rcases mem_zmod_2 b2 with (rfl | rfl)
257+
· rfl
258+
· exact (hb rfl).elim
259+
#align counterexample.ex_L.eq_zero_or_eq_zero_of_mul_eq_zero Counterexample.ExL.eq_zero_or_eq_zero_of_mul_eq_zero
260+
261+
instance can : CanonicallyOrderedCommSemiring L :=
262+
{ (inferInstance : OrderBot L),
263+
(inferInstance :
264+
OrderedCommSemiring L) with
265+
exists_add_of_le := @(exists_add_of_le)
266+
le_self_add := le_self_add
267+
eq_zero_or_eq_zero_of_mul_eq_zero := @(eq_zero_or_eq_zero_of_mul_eq_zero) }
268+
#align counterexample.ex_L.can Counterexample.ExL.can
269+
270+
/-- The elements `(1,0)` and `(1,1)` of `L` are different, but their doubles coincide.
271+
-/
272+
example : ∃ a b : L, a ≠ b ∧ 2 * a = 2 * b := by
273+
refine' ⟨⟨(1, 0), by simp⟩, 1, fun h : (⟨(1, 0), _⟩ : L) = ⟨⟨1, 1⟩, _⟩ => _, rfl⟩
274+
obtain F : (0 : ZMod 2) = 1 := congr_arg (fun j : L => j.1.2) h
275+
cases F
276+
277+
end ExL
278+
279+
end Counterexample

0 commit comments

Comments
 (0)