11module
22
3- def prime_fib : Unit :=
4- ()
3+ public import HumanEvalLean.Common.IsPrime
4+ meta import HumanEvalLean.Common.IsPrime
5+
6+ public section
7+
8+ /-! ## Implementation -/
9+
10+ def primeFib (n : Nat) : Nat :=
11+ go 0 1 (n - 1 )
12+ where
13+ go (i j n : Nat) : Nat :=
14+ if isPrime j then
15+ match n with
16+ | 0 => j
17+ | n' + 1 => go j (i + j) n'
18+ else
19+ go j (i + j) n
20+ partial_fixpoint
21+
22+ /-! ## Tests -/
23+
24+ example : primeFib 1 = 2 := by native_decide
25+ example : primeFib 2 = 3 := by native_decide
26+ example : primeFib 3 = 5 := by native_decide
27+ example : primeFib 4 = 13 := by native_decide
28+ example : primeFib 5 = 89 := by native_decide
29+ example : primeFib 6 = 233 := by native_decide
30+ example : primeFib 7 = 1597 := by native_decide
31+ example : primeFib 8 = 28657 := by native_decide
32+ example : primeFib 9 = 514229 := by native_decide
33+ example : primeFib 10 = 433494437 := by native_decide
34+
35+ /-! ## Verification -/
36+
37+ noncomputable def fib (n : Nat) :=
38+ match n with
39+ | 0 => 0
40+ | 1 => 1
41+ | n + 2 => fib n + fib (n + 1 )
42+
43+ theorem fib_pos {n : Nat} (h : 0 < n) :
44+ 0 < fib n := by
45+ induction n using Nat.strongRecOn
46+ rename_i n ih
47+ fun_cases fib n <;> grind
48+
49+ private theorem primeFib_eq_go_fib_fib {n : Nat} :
50+ primeFib n = primeFib.go (fib 0 ) (fib 1 ) (n - 1 ) := by
51+ grind [primeFib, fib]
52+
53+ private theorem primeFibGo_fib_fib {i n : Nat} :
54+ primeFib.go (fib i) (fib (i + 1 )) n =
55+ if isPrime (fib (i + 1 )) then
56+ match n with
57+ | 0 => fib (i + 1 )
58+ | n' + 1 => primeFib.go (fib (i + 1 )) (fib (i + 2 )) n'
59+ else
60+ primeFib.go (fib (i + 1 )) (fib (i + 2 )) n := by
61+ grind [primeFib.go.eq_def, fib]
62+
63+ set_option warn.sorry false in
64+ /--
65+ This lemma is a functional induction principle for `primeFib.go` assuming that
66+ there are infinitely many prime Fibonacci numbers, such that the function terminates.
67+ This is a mathematically hard problem, so we don't provide a proof.
68+ -/
69+ theorem primeFib_induction' (motive : Nat → Nat → Prop )
70+ (case1 : ∀ (i : Nat), isPrime (fib (i + 1 )) = true → motive i 0 )
71+ (case2 : ∀ (i : Nat), isPrime (fib (i + 1 )) = true → ∀ (n' : Nat), motive (i + 1 ) n' → motive i n'.succ)
72+ (case3 : ∀ (i n : Nat), ¬isPrime (fib (i + 1 )) = true → motive (i + 1 ) n → motive i n) (i n : Nat) :
73+ motive i n := by
74+ sorry
75+
76+ /--
77+ `primeFib n` is a prime number.
78+ -/
79+ theorem isPrime_primeFib {n : Nat} :
80+ IsPrime (primeFib n) := by
81+ suffices ∀ (i n : Nat), IsPrime (primeFib.go (fib i) (fib (i + 1 )) n) by
82+ grind [primeFib_eq_go_fib_fib]
83+ intro i n
84+ induction i, n using primeFib_induction'
85+ all_goals grind [primeFibGo_fib_fib, isPrime_eq_true_iff_isPrime]
86+
87+ /--
88+ `primeFib n` is a Fibonacci number.
89+ -/
90+ theorem exists_primeFib_eq_fib {n : Nat} :
91+ ∃ m, primeFib n = fib m := by
92+ suffices ∀ (i : Nat) (n : Nat), ∃ m, primeFib.go (fib i) (fib (i + 1 )) n = fib m by
93+ obtain ⟨m, hm⟩ := this 0 (n - 1 )
94+ exact ⟨m, by grind [primeFib_eq_go_fib_fib]⟩
95+ intro i n
96+ induction i, n using primeFib_induction' <;> grind [primeFibGo_fib_fib]
97+
98+ private theorem le_primeFibGo {i n : Nat} :
99+ fib (i + 1 ) ≤ primeFib.go (fib i) (fib (i + 1 )) n := by
100+ induction i, n using primeFib_induction'
101+ all_goals grind [fib, primeFibGo_fib_fib]
102+
103+ /--
104+ `primeFib i` is strictly monotone in `i`,
105+ starting from `i = 1` (`i = 0` is not considered a valid input by the problem description),
106+ -/
107+ theorem primeFib_mono {i j : Nat} (hi : 0 < i) (hj : i < j) :
108+ primeFib i < primeFib j := by
109+ suffices ∀ (i n : Nat), primeFib.go (fib i) (fib (i + 1 )) n < primeFib.go (fib i) (fib (i + 1 )) (n + 1 ) by
110+ obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hj
111+ induction k
112+ · specialize this 0 (i - 1 )
113+ grind [primeFib_eq_go_fib_fib]
114+ · grind [primeFib_eq_go_fib_fib]
115+ intro i n
116+ induction i, n using primeFib_induction'
117+ all_goals grind [primeFibGo_fib_fib, le_primeFibGo, fib, fib_pos,
118+ isPrime_eq_true_iff_isPrime, IsPrime]
119+
120+ /--
121+ Every prime Fibonacci number is contained in the image of `primeFib`.
122+ -/
123+ theorem exists_eq_primeFib_of_isPrime_fib {n : Nat} (h : IsPrime (fib n)) :
124+ ∃ m, primeFib m = fib n := by
125+ suffices ∀ (i : Nat) (hi : i < n), ∃ m, primeFib.go (fib i) (fib (i + 1 )) m = fib n by
126+ have hn : 0 < n := by grind [IsPrime, fib]
127+ obtain ⟨m, hm⟩ := this 0 (by grind)
128+ exact ⟨m + 1 , by grind [primeFib_eq_go_fib_fib]⟩
129+ intro i hi
130+ induction h : n - i - 1 generalizing i
131+ · exact ⟨0 , by grind [primeFibGo_fib_fib, isPrime_eq_true_iff_isPrime]⟩
132+ · rename_i k ih
133+ obtain ⟨m, hm⟩ := ih (i + 1 ) (by grind) (by grind)
134+ simp +singlePass only [primeFibGo_fib_fib]
135+ split
136+ · exact ⟨m + 1 , by grind⟩
137+ · exact ⟨m, by grind⟩
5138
6139/-!
7140## Prompt
@@ -67,4 +200,4 @@ def check(candidate):
67200 assert candidate(10) == 433494437
68201
69202```
70- -/
203+ -/
0 commit comments