lemma stirling_row_nonempty [simp]: "stirling_row n ≠ []" using length_stirling_row[of n] by (auto simp del: length_stirling_row)
subsubsection‹Efficient code›
text‹
Naively using the defining equations of the Stirling numbers of the first
kind to compute them leads to exponential run time due to repeated
computations. We can use memoisation to compute them row by row without
repeating computations, at the cost of computing a few unneeded values.
As a bonus, this is very efficient for applications where an entire row of
Stirling numbers is needed. ›
definition zip_with_prev :: "('a ==> 'a ==> 'b) ==> 'a ==> 'a list ==> 'b list" where"zip_with_prev f x xs = map2 f (x # xs) xs"
lemma zip_with_prev_altdef: "zip_with_prev f x xs = (if xs = [] then [] else f x (hd xs) # [f (xs!i) (xs!(i+1)). i ← [0..<length xs - 1]])" proof (cases xs) case Nil thenshow ?thesis by (simp add: zip_with_prev_def) next case (Cons y ys) thenhave"zip_with_prev f x xs = f x (hd xs) # zip_with_prev f y ys" by (simp add: zip_with_prev_def) alsohave"zip_with_prev f y ys = map (λi. f (xs ! i) (xs ! (i + 1))) [0..<length xs - 1]" unfolding Cons by (induct ys arbitrary: y)
(simp_all add: zip_with_prev_def upt_conv_Cons flip: map_Suc_upt del: upt_Suc) finallyshow ?thesis using Cons by simp qed
primrec stirling_row_aux where "stirling_row_aux n y [] = [1]"
| "stirling_row_aux n y (x#xs) = (y + n * x) # stirling_row_aux n x xs"
lemma stirling_row_aux_correct: "stirling_row_aux n y xs = zip_with_prev (λa b. a + n * b) y xs @ [1]" by (induct xs arbitrary: y) (simp_all add: zip_with_prev_def)
lemma stirling_row_code [code]: "stirling_row 0 = [1]" "stirling_row (Suc n) = stirling_row_aux n 0 (stirling_row n)" proof goal_cases case1 show ?caseby (simp add: stirling_row_def) next case2 have"stirling_row (Suc n) = 0 # [stirling_row n ! i + stirling_row n ! (i+1) * n. i ← [0..<n]] @ [1]" proof (rule nth_equalityI, goal_cases length nth) case (nth i) from nth have"i ≤ Suc n" by simp then consider "i = 0 ∨ i = Suc n" | "i > 0""i ≤ n" by linarith thenshow ?case proof cases case1 thenshow ?thesis by (auto simp: nth_stirling_row nth_append) next case2 thenshow ?thesis by (cases i) (simp_all add: nth_append nth_stirling_row) qed next case length thenshow ?caseby simp qed alsohave"0 # [stirling_row n ! i + stirling_row n ! (i+1) * n. i ← [0..<n]] @ [1] = zip_with_prev (λa b. a + n * b) 0 (stirling_row n) @ [1]" by (cases n) (auto simp add: zip_with_prev_altdef stirling_row_def hd_map simp del: upt_Suc) alsohave"… = stirling_row_aux n 0 (stirling_row n)" by (simp add: stirling_row_aux_correct) finallyshow ?case . qed
lemma stirling_code [code]: "stirling n k = (if k = 0 then (if n = 0 then 1 else 0) else if k > n then 0 else if k = n then 1 else stirling_row n ! k)" by (simp add: nth_stirling_row)
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.