@@ -176,3 +176,143 @@ theorem halting_problem (n) : ¬ computable_pred (λ c, (eval c n).dom)
176
176
| h := rice {f | (f n).dom} h nat.partrec.zero nat.partrec.none trivial
177
177
178
178
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'
0 commit comments