Skip to content

Commit 8b188ce

Browse files
committed
feat: port Archive.MiuLanguage.DecisionNec (leanprover-community#5472)
1 parent 55dfeba commit 8b188ce

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed

Archive.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import Archive.Imo.Imo2019Q4
2626
import Archive.Imo.Imo2020Q2
2727
import Archive.Imo.Imo2021Q1
2828
import Archive.MiuLanguage.Basic
29+
import Archive.MiuLanguage.DecisionNec
2930
import Archive.Sensitivity
3031
import Archive.Wiedijk100Theorems.AbelRuffini
3132
import Archive.Wiedijk100Theorems.AreaOfACircle
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/-
2+
Copyright (c) 2020 Gihan Marasingha. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Gihan Marasingha
5+
6+
! This file was ported from Lean 3 source module miu_language.decision_nec
7+
! leanprover-community/mathlib commit 3813d4ea1c6a34dbb472de66e73b8c6855b03964
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Archive.MiuLanguage.Basic
12+
import Mathlib.Data.List.Count
13+
import Mathlib.Data.Nat.ModEq
14+
import Mathlib.Tactic.Ring
15+
16+
/-!
17+
# Decision procedure: necessary condition
18+
19+
We introduce a condition `Decstr` and show that if a string `en` is `Derivable`, then `Decstr en`
20+
holds.
21+
22+
Using this, we give a negative answer to the question: is `"MU"` derivable?
23+
24+
## Tags
25+
26+
miu, decision procedure
27+
-/
28+
29+
30+
namespace Miu
31+
32+
open MiuAtom Nat List
33+
34+
/-!
35+
### Numerical condition on the `I` count
36+
37+
Suppose `st : Miustr`. Then `count I st` is the number of `I`s in `st`. We'll show, if
38+
`Derivable st`, then `count I st` must be 1 or 2 modulo 3. To do this, it suffices to show that if
39+
the `en : Miustr` is derived from `st`, then `count I en` moudulo 3 is either equal to or is twice
40+
`count I st`, modulo 3.
41+
-/
42+
43+
44+
/-- Given `st en : Miustr`, the relation `CountEquivOrEquivTwoMulMod3 st en` holds if `st` and
45+
`en` either have equal `count I`, modulo 3, or `count I en` is twice `count I st`, modulo 3.
46+
-/
47+
def CountEquivOrEquivTwoMulMod3 (st en : Miustr) : Prop :=
48+
let a := count I st
49+
let b := count I en
50+
b ≡ a [MOD 3] ∨ b ≡ 2 * a [MOD 3]
51+
#align miu.count_equiv_or_equiv_two_mul_mod3 Miu.CountEquivOrEquivTwoMulMod3
52+
53+
example : CountEquivOrEquivTwoMulMod3 "II" "MIUI" :=
54+
Or.inl rfl
55+
56+
example : CountEquivOrEquivTwoMulMod3 "IUIM" "MI" :=
57+
Or.inr rfl
58+
59+
/-- If `a` is 1 or 2 mod 3 and if `b` is `a` or twice `a` mod 3, then `b` is 1 or 2 mod 3.
60+
-/
61+
theorem mod3_eq_1_or_mod3_eq_2 {a b : ℕ} (h1 : a % 3 = 1 ∨ a % 3 = 2)
62+
(h2 : b % 3 = a % 3 ∨ b % 3 = 2 * a % 3) : b % 3 = 1 ∨ b % 3 = 2 := by
63+
cases' h2 with h2 h2
64+
· rw [h2]; exact h1
65+
· cases' h1 with h1 h1
66+
· right; simp [h2, mul_mod, h1, Nat.succ_lt_succ]
67+
· left; simp [h2, mul_mod, h1]
68+
#align miu.mod3_eq_1_or_mod3_eq_2 Miu.mod3_eq_1_or_mod3_eq_2
69+
70+
/-- `count_equiv_one_or_two_mod3_of_derivable` shows any derivable string must have a `count I` that
71+
is 1 or 2 modulo 3.
72+
-/
73+
theorem count_equiv_one_or_two_mod3_of_derivable (en : Miustr) :
74+
Derivable en → count I en % 3 = 1 ∨ count I en % 3 = 2 := by
75+
intro h
76+
induction' h with _ _ h_ih _ _ h_ih _ _ _ h_ih _ _ _ h_ih
77+
· left; rfl
78+
any_goals apply mod3_eq_1_or_mod3_eq_2 h_ih
79+
-- Porting note: `simp_rw [count_append]` usually doesn't work
80+
· left; rw [count_append, count_append]; rfl
81+
· right; simp_rw [count_append, count_cons, if_false, two_mul]
82+
· left; rw [count_append, count_append, count_append]
83+
simp_rw [count_cons_self, count_nil, count_cons, ite_false, add_right_comm, add_mod_right]
84+
· left; rw [count_append, count_append, count_append]
85+
simp only [ne_eq, count_cons_of_ne, count_nil, add_zero]
86+
#align miu.count_equiv_one_or_two_mod3_of_derivable Miu.count_equiv_one_or_two_mod3_of_derivable
87+
88+
/-- Using the above theorem, we solve the MU puzzle, showing that `"MU"` is not derivable.
89+
Once we have proved that `Derivable` is an instance of `DecidablePred`, this will follow
90+
immediately from `dec_trivial`.
91+
-/
92+
theorem not_derivable_mu : ¬Derivable "MU" := by
93+
intro h
94+
cases count_equiv_one_or_two_mod3_of_derivable _ h <;> contradiction
95+
#align miu.not_derivable_mu Miu.not_derivable_mu
96+
97+
/-!
98+
### Condition on `M`
99+
100+
That solves the MU puzzle, but we'll proceed by demonstrating the other necessary condition for a
101+
string to be derivable, namely that the string must start with an M and contain no M in its tail.
102+
-/
103+
104+
105+
/-- `Goodm xs` holds if `xs : Miustr` begins with `M` and has no `M` in its tail.
106+
-/
107+
def Goodm (xs : Miustr) : Prop :=
108+
List.headI xs = M ∧ ¬M ∈ List.tail xs
109+
#align miu.goodm Miu.Goodm
110+
111+
instance : DecidablePred Goodm := by unfold Goodm; infer_instance
112+
113+
/-- Demonstration that `"MI"` starts with `M` and has no `M` in its tail.
114+
-/
115+
theorem goodmi : Goodm [M, I] := by
116+
constructor
117+
· rfl
118+
· rw [tail, mem_singleton]; trivial
119+
#align miu.goodmi Miu.goodmi
120+
121+
/-!
122+
We'll show, for each `i` from 1 to 4, that if `en` follows by Rule `i` from `st` and if
123+
`Goodm st` holds, then so does `Goodm en`.
124+
-/
125+
126+
127+
theorem goodm_of_rule1 (xs : Miustr) (h₁ : Derivable (xs ++ ↑[I])) (h₂ : Goodm (xs ++ ↑[I])) :
128+
Goodm (xs ++ ↑[I, U]) := by
129+
cases' h₂ with mhead nmtail
130+
have : xs ≠ nil := by rintro rfl; contradiction
131+
constructor
132+
· -- Porting note: Original proof was `rwa [head_append] at * <;> exact this`.
133+
-- However, there is no `headI_append`
134+
cases xs
135+
· contradiction
136+
exact mhead
137+
· change ¬M ∈ tail (xs ++ ↑([I] ++ [U]))
138+
rw [← append_assoc, tail_append_singleton_of_ne_nil]
139+
· simp_rw [mem_append, not_or, and_true]; exact nmtail
140+
· exact append_ne_nil_of_ne_nil_left _ _ this
141+
#align miu.goodm_of_rule1 Miu.goodm_of_rule1
142+
143+
theorem goodm_of_rule2 (xs : Miustr) (_ : Derivable (M :: xs)) (h₂ : Goodm (M :: xs)) :
144+
Goodm (↑(M :: xs) ++ xs) := by
145+
constructor
146+
· rfl
147+
· cases' h₂ with mhead mtail
148+
contrapose! mtail
149+
rw [cons_append] at mtail
150+
exact (or_self_iff _).mp (mem_append.mp mtail)
151+
#align miu.goodm_of_rule2 Miu.goodm_of_rule2
152+
153+
theorem goodm_of_rule3 (as bs : Miustr) (h₁ : Derivable (as ++ ↑[I, I, I] ++ bs))
154+
(h₂ : Goodm (as ++ ↑[I, I, I] ++ bs)) : Goodm (as ++ ↑(U :: bs)) := by
155+
cases' h₂ with mhead nmtail
156+
have k : as ≠ nil := by rintro rfl; contradiction
157+
constructor
158+
· cases as
159+
· contradiction
160+
exact mhead
161+
· contrapose! nmtail
162+
rcases exists_cons_of_ne_nil k with ⟨x, xs, rfl⟩
163+
-- Porting note: `simp_rw [cons_append]` didn't work
164+
rw [cons_append] at nmtail; rw [cons_append, cons_append]
165+
dsimp only [tail] at nmtail ⊢
166+
simpa using nmtail
167+
#align miu.goodm_of_rule3 Miu.goodm_of_rule3
168+
169+
/-!
170+
The proof of the next lemma is identical, on the tactic level, to the previous proof.
171+
-/
172+
173+
174+
theorem goodm_of_rule4 (as bs : Miustr) (h₁ : Derivable (as ++ ↑[U, U] ++ bs))
175+
(h₂ : Goodm (as ++ ↑[U, U] ++ bs)) : Goodm (as ++ bs) := by
176+
cases' h₂ with mhead nmtail
177+
have k : as ≠ nil := by rintro rfl; contradiction
178+
constructor
179+
· cases as
180+
· contradiction
181+
exact mhead
182+
· contrapose! nmtail
183+
rcases exists_cons_of_ne_nil k with ⟨x, xs, rfl⟩
184+
-- Porting note: `simp_rw [cons_append]` didn't work
185+
rw [cons_append] at nmtail; rw [cons_append, cons_append]
186+
dsimp only [tail] at nmtail ⊢
187+
simpa using nmtail
188+
#align miu.goodm_of_rule4 Miu.goodm_of_rule4
189+
190+
/-- Any derivable string must begin with `M` and have no `M` in its tail.
191+
-/
192+
theorem goodm_of_derivable (en : Miustr) : Derivable en → Goodm en := by
193+
intro h
194+
induction h
195+
· exact goodmi
196+
· apply goodm_of_rule1 <;> assumption
197+
· apply goodm_of_rule2 <;> assumption
198+
· apply goodm_of_rule3 <;> assumption
199+
· apply goodm_of_rule4 <;> assumption
200+
#align miu.goodm_of_derivable Miu.goodm_of_derivable
201+
202+
/-!
203+
We put togther our two conditions to give one necessary condition `Decstr` for an `Miustr` to be
204+
derivable.
205+
-/
206+
207+
208+
/--
209+
`Decstr en` is the condition that `count I en` is 1 or 2 modulo 3, that `en` starts with `M`, and
210+
that `en` has no `M` in its tail. We automatically derive that this is a decidable predicate.
211+
-/
212+
def Decstr (en : Miustr) :=
213+
Goodm en ∧ (count I en % 3 = 1 ∨ count I en % 3 = 2)
214+
#align miu.decstr Miu.Decstr
215+
216+
instance : DecidablePred Decstr := by unfold Decstr; infer_instance
217+
218+
/-- Suppose `en : Miustr`. If `en` is `Derivable`, then the condition `Decstr en` holds.
219+
-/
220+
theorem decstr_of_der {en : Miustr} : Derivable en → Decstr en := by
221+
intro h
222+
constructor
223+
· exact goodm_of_derivable en h
224+
· exact count_equiv_one_or_two_mod3_of_derivable en h
225+
#align miu.decstr_of_der Miu.decstr_of_der
226+
227+
end Miu

0 commit comments

Comments
 (0)