import Mathlib /-! # Undecidability of Universality for RE Languages This file proves that universality cannot be decided for recursively enumerable (RE) languages. More precisely, the predicate "the partial function computed by code `c` halts on every input" is not computable. The proof mirrors that of emptiness undecidability, again via **Rice's theorem** (`ComputablePred.rice`). The semantic property `C = {f | ∀ n, (f n).Dom}` is non-trivial: the constant zero function `pure 0` is total (lies in `C`) while the everywhere-undefined function `fun _ ↦ Part.none` is not (lies outside `C`). ## Main results - `RE_universality_undecidable` — the predicate "code `c` halts on every input" is not computably decidable. -/ open Nat.Partrec /-- **Universality is undecidable for RE languages.** There is no algorithm that, given a code `c` for a partial-recursive function, decides whether `c` halts on every input (i.e., whether the domain of `c.eval` is all of `ℕ`). *Proof.* Apply Rice's theorem to the semantic property `C = {f : ℕ →. ℕ | ∀ n, (f n).Dom}`. The constant zero function `pure 0` is partial-recursive and lies in `C`, while the everywhere-undefined function `fun _ ↦ Part.none` is partial-recursive and does not. Hence `C` is non-trivial and therefore not computably decidable. -/ theorem RE_universality_undecidable : ¬ComputablePred (fun c : Code => ∀ n, (c.eval n).Dom) := by intro h have rice := ComputablePred.rice {f : ℕ →. ℕ | ∀ n, (f n).Dom} have h1 : ComputablePred (fun c : Code => c.eval ∈ {f : ℕ →. ℕ | ∀ n, (f n).Dom}) := by convert h using 1 -- The everywhere-undefined function is NOT total have none_not_total : (fun (_ : ℕ) => (Part.none : Part ℕ)) ∉ {f : ℕ →. ℕ | ∀ n, (f n).Dom} := fun h => h 0 -- The constant zero function IS total -- Rice gives: pure 0 ∈ C ⟹ (fun _ => Part.none) ∈ C, contradiction. exact none_not_total (rice h1 Nat.Partrec.zero Nat.Partrec.none (fun _ => trivial))