|
| 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