Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit bdd54ac

Browse files
committed
feat(data/computablility): reduced partrec
1 parent 00a2eb4 commit bdd54ac

File tree

5 files changed

+210
-13
lines changed

5 files changed

+210
-13
lines changed

data/computability/halting.lean

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,143 @@ theorem halting_problem (n) : ¬ computable_pred (λ c, (eval c n).dom)
176176
| h := rice {f | (f n).dom} h nat.partrec.zero nat.partrec.none trivial
177177

178178
end computable_pred
179+
180+
namespace nat
181+
open vector roption
182+
183+
/-- A simplified basis for `partrec`. -/
184+
inductive partrec' : ∀ {n}, (vector ℕ n →. ℕ) → Prop
185+
| prim {n f} : @primrec' n f → @partrec' n f
186+
| comp {m n f} (g : fin n → vector ℕ m →. ℕ) :
187+
partrec' f → (∀ i, partrec' (g i)) →
188+
partrec' (λ v, m_of_fn (λ i, g i v) >>= f)
189+
| rfind {n} {f : vector ℕ (n+1) → ℕ} : @partrec' (n+1) f →
190+
partrec' (λ v, rfind (λ n, some (f (n :: v) = 0)))
191+
192+
end nat
193+
194+
namespace nat.partrec'
195+
open vector partrec computable nat (partrec') nat.partrec'
196+
197+
theorem to_part {n f} (pf : @partrec' n f) : partrec f :=
198+
begin
199+
induction pf,
200+
case nat.partrec'.prim : n f hf { exact hf.to_prim.to_comp },
201+
case nat.partrec'.comp : m n f g _ _ hf hg {
202+
exact (vector_m_of_fn (λ i, hg i)).bind (hf.comp snd) },
203+
case nat.partrec'.rfind : n f _ hf {
204+
have := ((primrec.eq.comp primrec.id (primrec.const 0)).to_comp.comp
205+
(hf.comp (vector_cons.comp snd fst))).to₂.part,
206+
exact this.rfind },
207+
end
208+
209+
theorem of_eq {n} {f g : vector ℕ n →. ℕ}
210+
(hf : partrec' f) (H : ∀ i, f i = g i) : partrec' g :=
211+
(funext H : f = g) ▸ hf
212+
213+
theorem of_prim {n} {f : vector ℕ n → ℕ} (hf : primrec f) : @partrec' n f :=
214+
prim (nat.primrec'.of_prim hf)
215+
216+
theorem head {n : ℕ} : @partrec' n.succ (@head ℕ n) :=
217+
prim nat.primrec'.head
218+
219+
theorem tail {n f} (hf : @partrec' n f) : @partrec' n.succ (λ v, f v.tail) :=
220+
(hf.comp _ (λ i, @prim _ _ $ nat.primrec'.nth i.succ)).of_eq $
221+
λ v, by simp; rw [← of_fn_nth v.tail]; congr; funext i; simp
222+
223+
protected theorem bind {n f g}
224+
(hf : @partrec' n f) (hg : @partrec' (n+1) g) :
225+
@partrec' n (λ v, (f v).bind (λ a, g (a :: v))) :=
226+
(@comp n (n+1) g
227+
(λ i, fin.cases f (λ i v, some (v.nth i)) i) hg
228+
(λ i, begin
229+
refine fin.cases _ (λ i, _) i; simp *,
230+
exact prim (nat.primrec'.nth _)
231+
end)).of_eq $
232+
λ v, by simp [m_of_fn, roption.bind_assoc, pure]
233+
234+
protected theorem map {n f} {g : vector ℕ (n+1) → ℕ}
235+
(hf : @partrec' n f) (hg : @partrec' (n+1) g) :
236+
@partrec' n (λ v, (f v).map (λ a, g (a :: v))) :=
237+
by simp [(roption.bind_some_eq_map _ _).symm];
238+
exact hf.bind hg
239+
240+
def vec {n m} (f : vector ℕ n → vector ℕ m) :=
241+
∀ i, partrec' (λ v, (f v).nth i)
242+
243+
theorem vec.prim {n m f} (hf : @nat.primrec'.vec n m f) : vec f :=
244+
λ i, prim $ hf i
245+
246+
protected theorem nil {n} : @vec n 0 (λ _, nil) := λ i, i.elim0
247+
248+
protected theorem cons {n m} {f : vector ℕ n → ℕ} {g}
249+
(hf : @partrec' n f) (hg : @vec n m g) :
250+
vec (λ v, f v :: g v) :=
251+
λ i, fin.cases (by simp *) (λ i, by simp [hg i]) i
252+
253+
theorem idv {n} : @vec n n id := vec.prim nat.primrec'.idv
254+
255+
theorem comp' {n m f g} (hf : @partrec' m f) (hg : @vec n m g) :
256+
partrec' (λ v, f (g v)) :=
257+
(hf.comp _ hg).of_eq $ λ v, by simp
258+
259+
theorem comp₁ {n} (f : ℕ →. ℕ) {g : vector ℕ n → ℕ}
260+
(hf : @partrec' 1 (λ v, f v.head)) (hg : @partrec' n g) :
261+
@partrec' n (λ v, f (g v)) :=
262+
by simpa using hf.comp' (partrec'.cons hg partrec'.nil)
263+
264+
theorem rfind_opt {n} {f : vector ℕ (n+1) → ℕ}
265+
(hf : @partrec' (n+1) f) :
266+
@partrec' n (λ v, nat.rfind_opt (λ a, of_nat (option ℕ) (f (a :: v)))) :=
267+
((rfind $ (of_prim (primrec.nat_sub.comp (primrec.const 1) primrec.vector_head))
268+
.comp₁ (λ n, roption.some (1 - n)) hf)
269+
.bind ((prim nat.primrec'.pred).comp₁ nat.pred hf)).of_eq $
270+
λ v, roption.ext $ λ b, begin
271+
simp [nat.rfind_opt, -nat.mem_rfind],
272+
refine exists_congr (λ a,
273+
(and_congr (iff_of_eq _) iff.rfl).trans (and_congr_right (λ h, _))),
274+
{ congr; funext n,
275+
simp, cases f (n :: v); simp [nat.succ_ne_zero]; refl },
276+
{ have := nat.rfind_spec h,
277+
simp at this,
278+
cases f (a :: v) with c, {cases this},
279+
rw [← option.some_inj, eq_comm], refl }
280+
end
281+
282+
open nat.partrec.code
283+
theorem of_part : ∀ {n f}, partrec f → @partrec' n f :=
284+
suffices ∀ f, nat.partrec f → @partrec' 1 (λ v, f v.head), from
285+
λ n f hf, begin
286+
let g, swap,
287+
exact (comp₁ g (this g hf) (prim nat.primrec'.encode)).of_eq
288+
(λ i, by dsimp [g]; simp [encodek, roption.map_id']),
289+
end,
290+
λ f hf, begin
291+
rcases exists_code.1 hf with ⟨c, rfl⟩,
292+
simpa [eval_eq_rfind_opt] using
293+
(rfind_opt $ of_prim $ primrec.encode_iff.2 $ evaln_prim.comp $
294+
(primrec.vector_head.pair (primrec.const c)).pair $
295+
primrec.vector_head.comp primrec.vector_tail)
296+
end
297+
298+
theorem part_iff {n f} : @partrec' n f ↔ partrec f := ⟨to_part, of_part⟩
299+
300+
theorem part_iff₁ {f : ℕ →. ℕ} :
301+
@partrec' 1 (λ v, f v.head) ↔ partrec f :=
302+
part_iff.trans ⟨
303+
λ h, (h.comp $ (primrec.vector_of_fn $
304+
λ i, primrec.id).to_comp).of_eq (λ v, by simp),
305+
λ h, h.comp vector_head⟩
306+
307+
theorem part_iff₂ {f : ℕ → ℕ →. ℕ} :
308+
@partrec' 2 (λ v, f v.head v.tail.head) ↔ partrec₂ f :=
309+
part_iff.trans ⟨
310+
λ h, (h.comp $ vector_cons.comp fst $
311+
vector_cons.comp snd (const nil)).of_eq (λ v, by simp),
312+
λ h, h.comp vector_head (vector_head.comp vector_tail)⟩
313+
314+
theorem vec_iff {m n f} : @vec m n f ↔ computable f :=
315+
⟨λ h, by simpa using vector_of_fn (λ i, to_part (h i)),
316+
λ h i, of_prim $ vector_nth.comp h (primrec.const i)⟩
317+
318+
end nat.primrec'

data/computability/partrec.lean

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,17 @@ theorem list_append : computable₂ ((++) : list α → list α → list α) :=
284284
theorem list_concat : computable₂ (λ l (a:α), l ++ [a]) := primrec.list_concat.to_comp
285285
theorem list_length : computable (@list.length α) := primrec.list_length.to_comp
286286

287+
theorem vector_cons {n} : computable₂ (@vector.cons α n) := primrec.vector_cons.to_comp
288+
theorem vector_to_list {n} : computable (@vector.to_list α n) := primrec.vector_to_list.to_comp
289+
theorem vector_length {n} : computable (@vector.length α n) := primrec.vector_length.to_comp
290+
theorem vector_head {n} : computable (@vector.head α n) := primrec.vector_head.to_comp
291+
theorem vector_tail {n} : computable (@vector.tail α n) := primrec.vector_tail.to_comp
292+
theorem vector_nth {n} : computable₂ (@vector.nth α n) := primrec.vector_nth.to_comp
293+
theorem vector_nth' {n} : computable (@vector.nth α n) := primrec.vector_nth'.to_comp
294+
theorem vector_of_fn' {n} : computable (@vector.of_fn α n) := primrec.vector_of_fn'.to_comp
295+
296+
theorem fin_app {n} : computable₂ (@id (fin n → σ)) := primrec.fin_app.to_comp
297+
287298
protected theorem encode : computable (@encode α _) :=
288299
primrec.encode.to_comp
289300

@@ -463,8 +474,19 @@ theorem bind_decode2_iff {f : α →. σ} : partrec f ↔
463474
λ h, map_encode_iff.1 $ by simpa [encodek2]
464475
using (nat_iff.2 h).comp (@computable.encode α _)⟩
465476

477+
theorem vector_m_of_fn : ∀ {n} {f : fin n → α →. σ}, (∀ i, partrec (f i)) →
478+
partrec (λ (a : α), vector.m_of_fn (λ i, f i a))
479+
| 0 f hf := const _
480+
| (n+1) f hf := by simp [vector.m_of_fn]; exact
481+
(hf 0).bind (partrec.bind ((vector_m_of_fn (λ i, hf i.succ)).comp fst)
482+
(primrec.vector_cons.to_comp.comp (snd.comp fst) snd))
483+
466484
end partrec
467485

486+
@[simp] theorem vector.m_of_fn_roption_some {α n} : ∀ (f : fin n → α),
487+
vector.m_of_fn (λ i, roption.some (f i)) = roption.some (vector.of_fn f) :=
488+
vector.m_of_fn_pure
489+
468490
namespace computable
469491
variables {α : Type*} {β : Type*} {γ : Type*} {σ : Type*}
470492
variables [primcodable α] [primcodable β] [primcodable γ] [primcodable σ]
@@ -561,6 +583,16 @@ option_some_iff.1 $
561583
simp [IH, H, list.range_concat, option.bind]
562584
end
563585

586+
theorem list_of_fn : ∀ {n} {f : fin n → α → σ},
587+
(∀ i, computable (f i)) → computable (λ a, list.of_fn (λ i, f i a))
588+
| 0 f hf := const []
589+
| (n+1) f hf := by simp [list.of_fn_succ]; exact
590+
list_cons.comp (hf 0) (list_of_fn (λ i, hf i.succ))
591+
592+
theorem vector_of_fn {n} {f : fin n → α → σ}
593+
(hf : ∀ i, computable (f i)) : computable (λ a, vector.of_fn (λ i, f i a)) :=
594+
(partrec.vector_m_of_fn hf).of_eq $ λ a, by simp
595+
564596
end computable
565597

566598
namespace partrec

data/computability/partrec_code.lean

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -877,14 +877,17 @@ end
877877
section
878878
open partrec computable
879879

880+
theorem eval_eq_rfind_opt (c n) :
881+
eval c n = nat.rfind_opt (λ k, evaln k c n) :=
882+
roption.ext $ λ x, begin
883+
refine evaln_complete.trans (nat.rfind_opt_mono _).symm,
884+
intros a m n hl, apply evaln_mono hl,
885+
end
886+
880887
theorem eval_part : partrec₂ eval :=
881888
(rfind_opt (evaln_prim.to_comp.comp
882889
((snd.pair (fst.comp fst)).pair (snd.comp fst))).to₂).of_eq $
883-
λ a, roption.ext $ λ x, begin
884-
simp,
885-
refine (nat.rfind_opt_mono _).trans evaln_complete.symm,
886-
intros a m n hl, apply evaln_mono hl,
887-
end
890+
λ a, by simp [eval_eq_rfind_opt]
888891

889892
theorem fixed_point
890893
{f : code → code} (hf : computable f) : ∃ c : code, eval (f c) = eval c :=

data/computability/primrec.lean

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,20 +1187,20 @@ theorem tail {n f} (hf : @primrec' n f) : @primrec' n.succ (λ v, f v.tail) :=
11871187
(hf.comp _ (λ i, @nth _ i.succ)).of_eq $
11881188
λ v, by rw [← of_fn_nth v.tail]; congr; funext i; simp
11891189

1190-
def primvec {n m} (f : vector ℕ n → vector ℕ m) :=
1190+
def vec {n m} (f : vector ℕ n → vector ℕ m) :=
11911191
∀ i, primrec' (λ v, (f v).nth i)
11921192

1193-
protected theorem nil {n} : @primvec n 0 (λ _, nil) := λ i, i.elim0
1193+
protected theorem nil {n} : @vec n 0 (λ _, nil) := λ i, i.elim0
11941194

11951195
protected theorem cons {n m f g}
1196-
(hf : @primrec' n f) (hg : @primvec n m g) :
1197-
primvec (λ v, f v :: g v) :=
1196+
(hf : @primrec' n f) (hg : @vec n m g) :
1197+
vec (λ v, f v :: g v) :=
11981198
λ i, fin.cases (by simp *) (λ i, by simp [hg i]) i
11991199

1200-
theorem idv {n} : @primvec n n id := nth
1200+
theorem idv {n} : @vec n n id := nth
12011201

12021202
theorem comp' {n m f g}
1203-
(hf : @primrec' m f) (hg : @primvec n m g) :
1203+
(hf : @primrec' m f) (hg : @vec n m g) :
12041204
primrec' (λ v, f (g v)) :=
12051205
(hf.comp _ hg).of_eq $ λ v, by simp
12061206

@@ -1337,8 +1337,8 @@ prim_iff.trans ⟨
13371337
vector_cons.comp snd (primrec.const nil)).of_eq (λ v, by simp),
13381338
λ h, h.comp vector_head (vector_head.comp vector_tail)⟩
13391339

1340-
theorem primvec_iff {m n f} :
1341-
@primvec m n f ↔ primrec f :=
1340+
theorem vec_iff {m n f} :
1341+
@vec m n f ↔ primrec f :=
13421342
⟨λ h, by simpa using vector_of_fn (λ i, to_prim (h i)),
13431343
λ h i, of_prim $ vector_nth.comp h (primrec.const i)⟩
13441344

data/vector2.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,26 @@ by simp [nth_zero]
6969
(a : α) (v : vector α n) (i : fin n) : nth (a :: v) i.succ = nth v i :=
7070
by rw [← nth_tail, tail_cons]
7171

72+
def {u} m_of_fn {m} [monad m] {α : Type u} : ∀ {n}, (fin n → m α) → m (vector α n)
73+
| 0 f := pure nil
74+
| (n+1) f := do a ← f 0, v ← m_of_fn (λi, f i.succ), pure (a :: v)
75+
76+
theorem m_of_fn_pure {m} [monad m] [is_lawful_monad m] {α} :
77+
∀ {n} (f : fin n → α), @m_of_fn m _ _ _ (λ i, pure (f i)) = pure (of_fn f)
78+
| 0 f := rfl
79+
| (n+1) f := by simp [m_of_fn, @m_of_fn_pure n, of_fn]
80+
81+
def {u} mmap {m} [monad m] {α} {β : Type u} (f : α → m β) :
82+
∀ {n}, vector α n → m (vector β n)
83+
| _ ⟨[], rfl⟩ := pure nil
84+
| _ ⟨a::l, rfl⟩ := do h' ← f a, t' ← mmap ⟨l, rfl⟩, pure (h' :: t')
85+
86+
@[simp] theorem mmap_nil {m} [monad m] {α β} (f : α → m β) :
87+
mmap f nil = pure nil := rfl
88+
89+
@[simp] theorem mmap_cons {m} [monad m] {α β} (f : α → m β) (a) :
90+
∀ {n} (v : vector α n), mmap f (a::v) =
91+
do h' ← f a, t' ← mmap f v, pure (h' :: t')
92+
| _ ⟨l, rfl⟩ := rfl
93+
7294
end vector

0 commit comments

Comments
 (0)