Skip to content

Commit 1482686

Browse files
authored
Merge pull request #52 from jessealama/type-class-improvements
2 parents d33edef + 5519658 commit 1482686

7 files changed

Lines changed: 115 additions & 63 deletions

File tree

Urm/Basic.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ theorem init_state (inputs : List ℕ) : (init inputs).state = State.fromInputs
215215
theorem ext {c₁ c₂ : Config} (hpc : c₁.pc = c₂.pc) (hstate : c₁.state = c₂.state) : c₁ = c₂ := by
216216
cases c₁; cases c₂; simp only at hpc hstate; simp [hpc, hstate]
217217

218+
instance : Inhabited Config := ⟨init []⟩
219+
220+
instance : Repr Config where
221+
reprPrec c _ := s!"Config(pc={c.pc})"
222+
218223
end Config
219224

220225
end Urm

Urm/Composition/Construction.lean

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,51 @@ open Program
1515
def gPhase (base n : ℕ) (pG : Program) (i : ℕ) : Program :=
1616
(clearRegisters base).concat ((copyRegisterRange (base + 1) 0 n).concat (pG.concat [Instr.T 0 (base + n + 1 + i)]))
1717

18+
/-- Helper to map gPhase over a list of indices. -/
19+
def gPhaseList (n base : ℕ) (pGs : Fin m → Program) (indices : List (Fin m)) : List Program :=
20+
indices.map (fun i => gPhase base n (pGs i) i.val)
21+
1822
def allGPhases (m n base : ℕ) (pGs : Fin m → Program) : Program :=
19-
(List.finRange m).foldl (fun acc i => acc.concat (gPhase base n (pGs i) i.val)) []
23+
(gPhaseList n base pGs (List.finRange m)).prod
2024

2125
def allGPhases_prefix (m n base : ℕ) (pGs : Fin m → Program) (i : ℕ) : Program :=
22-
(List.finRange m).take i |>.foldl (fun acc j => acc.concat (gPhase base n (pGs j) j.val)) []
26+
(gPhaseList n base pGs ((List.finRange m).take i)).prod
2327

2428
def allGPhases_suffix (m n base : ℕ) (pGs : Fin m → Program) (i : ℕ) : Program :=
25-
(List.finRange m).drop i |>.foldl (fun acc j => acc.concat (gPhase base n (pGs j) j.val)) []
26-
27-
theorem foldl_concat_eq_acc_concat {α : Type*} (f : α → Program) (l : List α) (acc : Program) :
28-
l.foldl (fun a x => a.concat (f x)) acc = acc.concat (l.foldl (fun a x => a.concat (f x)) []) := by
29-
induction l generalizing acc with
30-
| nil => simp only [List.foldl_nil, concat_nil_right]
31-
| cons x xs ih => simp only [List.foldl_cons, concat_nil_left]; rw [ih (acc.concat (f x)), ih (f x), concat_assoc]
29+
(gPhaseList n base pGs ((List.finRange m).drop i)).prod
3230

3331
theorem allGPhases_split (m n base : ℕ) (pGs : Fin m → Program) (i : ℕ) (_hi : i ≤ m) :
3432
allGPhases m n base pGs = (allGPhases_prefix m n base pGs i).concat (allGPhases_suffix m n base pGs i) := by
35-
simp only [allGPhases, allGPhases_prefix, allGPhases_suffix]
36-
conv_lhs => rw [(List.take_append_drop i (List.finRange m)).symm]
37-
simp only [List.foldl_append]
38-
exact foldl_concat_eq_acc_concat (fun j => gPhase base n (pGs j) j.val) _ _
33+
simp only [allGPhases, allGPhases_prefix, allGPhases_suffix, gPhaseList]
34+
rw [show (List.finRange m).map (fun i => gPhase base n (pGs i) i.val) =
35+
((List.finRange m).take i).map (fun i => gPhase base n (pGs i) i.val) ++
36+
((List.finRange m).drop i).map (fun i => gPhase base n (pGs i) i.val) by
37+
rw [← List.map_append, List.take_append_drop]]
38+
rw [List.prod_append]
39+
rfl
3940

4041
theorem allGPhases_prefix_full (m n base : ℕ) (pGs : Fin m → Program) :
4142
allGPhases_prefix m n base pGs m = allGPhases m n base pGs := by
42-
simp only [allGPhases_prefix, allGPhases]; congr 1; simp
43+
simp only [allGPhases_prefix, allGPhases, gPhaseList]; congr 1; simp
44+
45+
/-- Decompose suffix when start < m: first gPhase followed by remaining suffix. -/
46+
theorem allGPhases_suffix_cons {m n base : ℕ} (pGs : Fin m → Program) (start : ℕ) (hstart : start < m) :
47+
allGPhases_suffix m n base pGs start =
48+
(gPhase base n (pGs ⟨start, hstart⟩) start).concat (allGPhases_suffix m n base pGs (start + 1)) := by
49+
simp only [allGPhases_suffix, gPhaseList]
50+
rw [List.drop_eq_getElem_cons (by simp; exact hstart), List.map_cons, List.prod_cons]
51+
simp only [List.getElem_finRange]
52+
rfl
53+
54+
/-- Decompose prefix when taking one more: previous prefix followed by the next gPhase. -/
55+
theorem allGPhases_prefix_succ {m n base : ℕ} (pGs : Fin m → Program) (i : ℕ) (hi : i < m) :
56+
allGPhases_prefix m n base pGs (i + 1) =
57+
(allGPhases_prefix m n base pGs i).concat (gPhase base n (pGs ⟨i, hi⟩) i) := by
58+
simp only [allGPhases_prefix, gPhaseList]
59+
rw [List.take_succ_eq_append_getElem (by simp; exact hi : i < (List.finRange m).length)]
60+
rw [List.map_append, List.map_singleton, List.prod_append, List.prod_singleton]
61+
simp only [List.getElem_finRange]
62+
rfl
4363

4464
def finalPhase (m n base : ℕ) (pF : Program) : Program :=
4565
(clearRegisters base).concat ((transferResultsToInputs (base + n + 1) m).concat pF)

Urm/Composition/Correctness.lean

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,8 @@ theorem comp_general_halts_imp_gi_dom
6161
obtain ⟨sSavePrefix, _, hsSavePrefix_eq, cSuffix, hSuffix_steps, hSuffix_halted⟩ :=
6262
Halts.suffix_of_concat_sf hSaveGPhases_halts hSavePrefix_sf
6363
have hSuffix_i_eq : allGPhases_suffix m n base pGs i.val =
64-
(gPhase base n (pGs i) i.val).concat (allGPhases_suffix m n base pGs (i.val + 1)) := by
65-
simp only [allGPhases_suffix]
66-
rw [show (List.finRange m).drop i.val = i :: (List.finRange m).drop (i.val + 1) from by
67-
rw [List.drop_eq_getElem_cons]; · congr 1; simp only [List.finRange, List.getElem_ofFn]
68-
· simp only [List.length_finRange]; exact i.isLt,
69-
List.foldl_cons, concat_nil_left]
70-
exact foldl_concat_eq_acc_concat _ _ _
64+
(gPhase base n (pGs i) i.val).concat (allGPhases_suffix m n base pGs (i.val + 1)) :=
65+
allGPhases_suffix_cons pGs i.val i.isLt
7166
rw [hSuffix_i_eq] at hSuffix_steps hSuffix_halted
7267
obtain ⟨_, hGPhase_i_steps, hGPhase_i_halted⟩ :=
7368
prefix_of_concat_from_zero hSuffix_steps hSuffix_halted hGPhase_i_sf

Urm/Composition/Halting.lean

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,21 @@ theorem allGPhases_halts_from_saved_inputs {m n base : ℕ} {pGs : Fin m → Pro
8585
(hSaved : ∀ j : ℕ, (hj : j < n) → s.read (base + 1 + j) = inputs ⟨j, hj⟩) :
8686
∃ c, Steps (allGPhases m n base pGs) ⟨0, s⟩ c ∧ c.isHalted (allGPhases m n base pGs) := by
8787
induction m with
88-
| zero => simp only [allGPhases, List.finRange_zero, List.foldl_nil]
89-
exact ⟨⟨0, s⟩, Relation.ReflTransGen.refl, by simp⟩
88+
| zero =>
89+
have hAllGPhases_zero : allGPhases 0 n base pGs = [] := by
90+
simp only [allGPhases, gPhaseList, List.finRange_zero, List.map_nil, List.prod_nil]; rfl
91+
simp only [hAllGPhases_zero]
92+
exact ⟨⟨0, s⟩, Relation.ReflTransGen.refl, by simp⟩
9093
| succ m' ih =>
91-
simp only [allGPhases]
92-
rw [List.finRange_succ_last, List.foldl_append, List.foldl_map, List.foldl_cons, List.foldl_nil]
9394
let pGs' : Fin m' → Program := fun i => pGs i.castSucc
94-
have hPrefix_eq : List.foldl (fun x y => Program.concat x (gPhase base n (pGs y.castSucc) ↑y.castSucc))
95-
[] (List.finRange m') = allGPhases m' n base pGs' := rfl
96-
rw [hPrefix_eq]
95+
have hAllGPhases_succ : allGPhases (m' + 1) n base pGs =
96+
(allGPhases m' n base pGs').concat (gPhase base n (pGs (Fin.last m')) m') := by
97+
simp only [allGPhases, gPhaseList]
98+
rw [List.finRange_succ_last, List.map_append, List.map_singleton, List.prod_append, List.prod_singleton]
99+
show (Program.concat _ _) = (Program.concat _ _)
100+
simp only [List.map_map, Fin.val_last, Function.comp_def]
101+
rfl
102+
rw [hAllGPhases_succ]
97103
obtain ⟨cPrefix, hPrefix_steps, hPrefix_halted⟩ := ih (fun i => hpGs_sf i.castSucc)
98104
(fun i => hpGs_max i.castSucc) (fun i => hpGs_halts i.castSucc)
99105
have hPrefix_sf := allGPhases_isStandardForm (n := n) (base := base) (fun i => hpGs_sf i.castSucc)
@@ -144,20 +150,23 @@ theorem allGPhases_suffix_preserves_earlier_results {m n base : ℕ} {pGs : Fin
144150
(hhalted : c'.isHalted (allGPhases_suffix m n base pGs start)) :
145151
c'.state.read (base + n + 1 + k) = s.read (base + n + 1 + k) := by
146152
match m with
147-
| 0 => simp only [allGPhases_suffix, List.finRange_zero, List.drop_nil, List.foldl_nil] at hsteps hhalted
148-
rw [Steps.halts_unique hsteps hhalted Relation.ReflTransGen.refl (by simp)]
153+
| 0 =>
154+
have hSuffix_zero : allGPhases_suffix 0 n base pGs start = [] := by
155+
simp only [allGPhases_suffix, gPhaseList, List.finRange_zero, List.drop_nil, List.map_nil, List.prod_nil]; rfl
156+
simp only [hSuffix_zero] at hsteps hhalted
157+
rw [Steps.halts_unique hsteps hhalted Relation.ReflTransGen.refl (by simp)]
149158
| Nat.succ m' =>
150159
by_cases hEmpty : start ≥ m' + 1
151160
· have hSuffix_empty : allGPhases_suffix (m' + 1) n base pGs start = [] := by
152-
simp only [allGPhases_suffix]; rw [List.drop_eq_nil_of_le (by simp; omega)]; rfl
161+
simp only [allGPhases_suffix, gPhaseList]
162+
rw [List.drop_eq_nil_of_le (by simp; omega)]
163+
rfl
153164
rw [hSuffix_empty] at hsteps hhalted
154165
rw [Steps.halts_unique hsteps hhalted Relation.ReflTransGen.refl (by simp)]
155166
· push_neg at hEmpty
156167
have hSuffix_decomp : allGPhases_suffix (m' + 1) n base pGs start =
157-
(gPhase base n (pGs ⟨start, hEmpty⟩) start).concat (allGPhases_suffix (m' + 1) n base pGs (start + 1)) := by
158-
simp only [allGPhases_suffix]
159-
rw [List.drop_eq_getElem_cons (by simp; exact hEmpty), List.foldl_cons, foldl_concat_eq_acc_concat]
160-
simp only [concat_nil_left, List.getElem_finRange]; congr 2
168+
(gPhase base n (pGs ⟨start, hEmpty⟩) start).concat (allGPhases_suffix (m' + 1) n base pGs (start + 1)) :=
169+
allGPhases_suffix_cons pGs start hEmpty
161170
rw [hSuffix_decomp] at hsteps hhalted
162171
let dFirst := decompose_concat hsteps hhalted (gPhase_isStandardForm (hpGs_sf ⟨start, hEmpty⟩))
163172
obtain ⟨cRest, hRest_steps, hRest_halted⟩ := dFirst.halts_right
@@ -198,11 +207,8 @@ theorem allGPhases_saves_result {m n : ℕ} [NeZero m] {pF : Program} {pGs : Fin
198207
obtain ⟨sSavePrefix, hSavePrefix_steps, cSuffix, hSuffix_steps, hSuffix_halted⟩ :=
199208
suffix_of_concat_from_zero hsteps hhalted hSavePrefix_sf
200209
have hPrefixDecomp : allGPhases_prefix m n base pGs (i.val + 1) =
201-
(allGPhases_prefix m n base pGs i.val).concat (gPhase base n (pGs i) i.val) := by
202-
simp only [allGPhases_prefix]
203-
rw [List.take_succ_eq_append_getElem (by simp : i.val < (List.finRange m).length),
204-
List.foldl_append, List.foldl_cons, List.foldl_nil, foldl_concat_eq_acc_concat]
205-
simp only [List.getElem_finRange]; congr 1
210+
(allGPhases_prefix m n base pGs i.val).concat (gPhase base n (pGs i) i.val) :=
211+
allGPhases_prefix_succ pGs i.val i.isLt
206212
have hSavePrefixI_sf := hSave_sf.concat (allGPhases_prefix_isStandardForm (n := n) (base := base) hGs_sf i.val)
207213
have hSavePrefix_eq : saveInputs.concat (allGPhases_prefix m n base pGs (i.val + 1)) =
208214
(saveInputs.concat (allGPhases_prefix m n base pGs i.val)).concat (gPhase base n (pGs i) i.val) := by
@@ -229,7 +235,9 @@ theorem allGPhases_saves_result {m n : ℕ} [NeZero m] {pF : Program} {pGs : Fin
229235
have hSaved_i : ∀ k : ℕ, (hk : k < n) → sSavePrefixI.read (base + 1 + k) = inputs ⟨k, hk⟩ := by
230236
intro k hk
231237
by_cases hi_zero : i.val = 0
232-
· simp only [hi_zero, allGPhases_prefix, List.take_zero, List.foldl_nil, concat_nil_right] at hSavePrefixI_steps
238+
· have hPrefix_zero : allGPhases_prefix m n base pGs 0 = [] := by
239+
simp only [allGPhases_prefix, gPhaseList, List.take_zero, List.map_nil, List.prod_nil]; rfl
240+
simp only [hi_zero, hPrefix_zero, concat_nil_right] at hSavePrefixI_steps
233241
rw [show sSavePrefixI = cSave.state from
234242
congrArg Config.state (Steps.halts_unique hSavePrefixI_steps (by simp) hSave_steps' hSave_halted'),
235243
hSave_state_sSave, hAfterSave k hk]

Urm/Composition/Preservation.lean

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,16 @@ theorem allGPhases_prefix_preserves_saved_inputs (m n base : ℕ) (pGs : Fin m
137137
intro r hr_lo hr_hi
138138
induction k generalizing s s' c' with
139139
| zero =>
140-
simp only [allGPhases_prefix, List.take_zero, List.foldl_nil] at hsteps hhalted
140+
have hPrefix_zero : allGPhases_prefix m n base pGs 0 = [] := by
141+
simp only [allGPhases_prefix, gPhaseList, List.take_zero, List.map_nil, List.prod_nil]; rfl
142+
simp only [hPrefix_zero] at hsteps hhalted
141143
simp only [← hstate_eq, Steps.halts_unique hsteps hhalted (.refl _) (by simp)]
142144
| succ k' ih =>
143145
have hk'_lt : k' < m := Nat.lt_of_succ_le hk
144146
let k'_fin : Fin m := ⟨k', hk'_lt⟩
145-
have htake_eq : (List.finRange m).take (k' + 1) = (List.finRange m).take k' ++ [k'_fin] := by
146-
rw [List.take_add_one, getElem?_pos (List.finRange m) k' (by simp [hk'_lt]), Option.toList_some]
147-
simp only [List.finRange, List.getElem_ofFn, k'_fin]
148147
have hPrefix_succ_eq : allGPhases_prefix m n base pGs (k' + 1) =
149-
(allGPhases_prefix m n base pGs k').concat (gPhase base n (pGs k'_fin) k') := by
150-
simp only [allGPhases_prefix]
151-
rw [htake_eq, List.foldl_append, List.foldl_cons, List.foldl_nil]
148+
(allGPhases_prefix m n base pGs k').concat (gPhase base n (pGs k'_fin) k') :=
149+
allGPhases_prefix_succ pGs k' hk'_lt
152150
rw [hPrefix_succ_eq] at hsteps hhalted
153151
obtain ⟨sMid, hMid_steps, ⟨cGPhase, hGPhase_steps, hGPhase_halted⟩⟩ :=
154152
suffix_of_concat_from_zero hsteps hhalted (allGPhases_prefix_isStandardForm hpGs_sf k')

Urm/Composition/StandardForm.lean

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,23 @@ theorem gPhase_isStandardForm {base n : ℕ} {pG : Program} {i : ℕ} (hG : pG.I
2424
((copyRegisterRange_isStandardForm (base + 1) 0 n).concat
2525
(hG.concat (single_T_isStandardForm 0 (base + n + 1 + i))))
2626

27-
private theorem foldl_preserves_isStandardForm {α : Type*} (l : List α) (f : Program → α → Program)
28-
(hf : ∀ acc a, acc.IsStandardForm → (f acc a).IsStandardForm) (acc : Program) (hacc : acc.IsStandardForm) :
29-
(l.foldl f acc).IsStandardForm := by
30-
induction l generalizing acc with
31-
| nil => exact hacc
32-
| cons x xs ih => simp only [List.foldl_cons]; exact ih (f acc x) (hf acc x hacc)
27+
private theorem prod_preserves_isStandardForm (l : List Program)
28+
(hl : ∀ p ∈ l, p.IsStandardForm) : l.prod.IsStandardForm := by
29+
induction l with
30+
| nil => exact straightLine_isStandardForm rfl
31+
| cons x xs ih =>
32+
rw [List.prod_cons]
33+
show (x.concat xs.prod).IsStandardForm
34+
exact Program.IsStandardForm.concat (hl x List.mem_cons_self)
35+
(ih (fun p hp => hl p (List.mem_cons_of_mem x hp)))
3336

3437
theorem allGPhases_isStandardForm {m n base : ℕ} {pGs : Fin m → Program}
3538
(hGs : ∀ i, (pGs i).IsStandardForm) : (allGPhases m n base pGs).IsStandardForm := by
36-
simp only [allGPhases]
37-
exact foldl_preserves_isStandardForm _ _ (fun acc i hacc => hacc.concat (gPhase_isStandardForm (hGs i)))
38-
[] (straightLine_isStandardForm rfl)
39+
unfold allGPhases gPhaseList
40+
exact prod_preserves_isStandardForm _ (fun p hp => by
41+
simp only [List.mem_map] at hp
42+
obtain ⟨i, _, rfl⟩ := hp
43+
exact gPhase_isStandardForm (hGs i))
3944

4045
theorem finalPhase_isStandardForm {m n base : ℕ} {pF : Program} (hF : pF.IsStandardForm) :
4146
(finalPhase m n base pF).IsStandardForm := by
@@ -52,15 +57,19 @@ theorem composeGeneral_isStandardForm {m n : ℕ} {pF : Program} {pGs : Fin m
5257

5358
theorem allGPhases_prefix_isStandardForm {m n base : ℕ} {pGs : Fin m → Program}
5459
(hGs : ∀ i, (pGs i).IsStandardForm) (k : ℕ) : (allGPhases_prefix m n base pGs k).IsStandardForm := by
55-
simp only [allGPhases_prefix]
56-
exact foldl_preserves_isStandardForm _ _ (fun acc j hacc => hacc.concat (gPhase_isStandardForm (hGs j)))
57-
[] (straightLine_isStandardForm rfl)
60+
unfold allGPhases_prefix gPhaseList
61+
exact prod_preserves_isStandardForm _ (fun p hp => by
62+
simp only [List.mem_map] at hp
63+
obtain ⟨i, _, rfl⟩ := hp
64+
exact gPhase_isStandardForm (hGs i))
5865

5966
theorem allGPhases_suffix_isStandardForm {m n base : ℕ} {pGs : Fin m → Program}
6067
(hGs : ∀ i, (pGs i).IsStandardForm) (k : ℕ) : (allGPhases_suffix m n base pGs k).IsStandardForm := by
61-
simp only [allGPhases_suffix]
62-
exact foldl_preserves_isStandardForm _ _ (fun acc j hacc => hacc.concat (gPhase_isStandardForm (hGs j)))
63-
[] (straightLine_isStandardForm rfl)
68+
unfold allGPhases_suffix gPhaseList
69+
exact prod_preserves_isStandardForm _ (fun p hp => by
70+
simp only [List.mem_map] at hp
71+
obtain ⟨i, _, rfl⟩ := hp
72+
exact gPhase_isStandardForm (hGs i))
6473

6574
theorem saveInputs_isStandardForm (base n : ℕ) : (copyRegisterRange 0 (base + 1) n).IsStandardForm :=
6675
copyRegisterRange_isStandardForm 0 (base + 1) n

Urm/Concat.lean

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Jesse Alama
66

77
import Urm.Execution
88
import Urm.StraightLine
9+
import Mathlib.Algebra.Group.Defs
910

1011
/-! # Program Concatenation
1112
@@ -82,6 +83,22 @@ theorem concat_assoc (p1 p2 p3 : Program) :
8283
| T m n => simp [Instr.shiftJumps]
8384
| J m n q => simp [Instr.shiftJumps]; omega
8485

86+
/-- Program concatenation forms a semigroup.
87+
Note: This uses `concat` (which shifts jumps), not raw list append. -/
88+
instance : Semigroup Program where
89+
mul := concat
90+
mul_assoc := concat_assoc
91+
92+
/-- Program concatenation forms a monoid with empty program as identity. -/
93+
instance : Monoid Program where
94+
one := []
95+
one_mul := concat_nil_left
96+
mul_one := concat_nil_right
97+
98+
/-- Relates `.concat` to `*` for algebraic automation.
99+
Use with `simp only [concat_eq_mul, mul_assoc]` to leverage Monoid associativity. -/
100+
theorem concat_eq_mul (p q : Program) : p.concat q = p * q := rfl
101+
85102
/-- Get instruction from concatenated program in the first part. -/
86103
theorem getInstr_concat_left {p1 p2 : Program} (i : ℕ) (hi : i < p1.length) :
87104
(p1.concat p2).getInstr i = p1.getInstr i := by

0 commit comments

Comments
 (0)