Isabelle/Isar(その21)

 さて,これまでは数列を定理の中で,言わば局所的に定義しましたが,セッション全体を通して大域的に定義すると,システムが証明に便利な定理を自動的に用意してくれます.

 まず,数列Xを次のように定義します.

fun X :: "nat => real" where
  "X 0 = 0" | "X (Suc n) = 2 * X n + 1"

1行目は見ての通り写像としてのタイプそして,2行目で帰納的定義を与えている訳ですが,ここでも,メタレベルの全称量化が略された(もしくはパターンマッチングを想定した開いた)式を用いる点が特徴で,その為,連言ではなく選言になっています(!! n. が全体に掛かっている).

 このように定義すると,IsarはこのXに従う4つの定理を作成します.名前で検索すると...

find_theorems name: "X."

Outputは

searched for:
name: "X."

found 4 theorem(s):

Scratch.X.cases: (?x = 0 ⟹ ?P) ⟹ (⋀n. ?x = Suc n ⟹ ?P) ⟹ ?P
Scratch.X.induct: ?P 0 ⟹ (⋀n. ?P n ⟹ ?P (Suc n)) ⟹ ?P ?a0.0
Scratch.X.simps(1): X 0 = 0
Scratch.X.simps(2): X (Suc ?n) = 2 * X ?n + 1

これらはsimpで参照される属性を与えられているので,直ちに

lemma "X n = 2 ^ n - 1"
  by (induct n, simp_all)

が通ります.

 また,if then elseを用いて

fun X :: "nat => real" where
  "X n = (if n = 0 then 0 else  2 * X (n - 1) + 1)"

のように定義することも出来,この場合の定理は

searched for:
name: "X."

found 3 theorem(s):

Scratch.X.cases: (⋀n. ?x = n ⟹ ?P) ⟹ ?P
Scratch.X.induct: (⋀n. (n ≠ 0 ⟹ ?P (n - 1)) ⟹ ?P n) ⟹ ?P ?a0.0
Scratch.X.simps: X ?n = (if ?n = 0 then 0 else 2 * X (?n - 1) + 1)

となりますが,上記のlemmaの証明はそのまま通ります.