record Env : Set where
field
varn : N
vari : N
open Env
型に対応する値の導入(intro)
record {varx = zero ; vary = suc zero}
record の値のアクセス(elim)
(env : Env) → varx env
Agda の基本 data
一つでも存在すること
どちらかが成り立つ型を Data 型 で書く
data bt {n : Level} (A : Set n) : Set n where
leaf : bt A
node : (key : N) → (value : A) → (left : bt A ) → (right : bt A ) → bt A
記述する際の基本的な例を以下に挙げる
datasample : bt → N
datasample leaf = zero
datasample (node key value left right) = suc zero
Agda の基本 短縮記法
with を使用することでその変数のパターンマッチすることもできる
patternmatch-default : Env → N
patternmatch-default record { varn = zero ; vari = i } = i
patternmatch-default record { varn = suc n ; vari = i } = patternmatch-default record { varn = n ; vari = suc i }
patternmatch-extraction : env → N
patternmatch-extraction env with varn env
patternmatch-extraction zero = vari env
patternmatch-extraction suc n = patternmatch-extraction record { varn = n ; vari = suc (vari env) }
... | `を使用することで関数の定義部分を省略できる
patternmatch-extraction' : env → N
patternmatch-extraction' env with varn env
... | zero = vari env
... | suc n = patternmatch-default' record { varn = n ; vari = suc (vari env) }
Gears Agda の記法
Agda では関数の再帰呼び出しが可能であるが、CbC で再起処理を実装しても値は帰って来ない
Agda で実装を行う際には再帰呼び出しを行わないようにする。
plus-com : {l : Level} {t : Set l} → Env → (next : Env → t) → (exit : Env → t) → t
plus-com env next exit with vary env
... | zero = exit (record { varx = varx env ; vary = vary env })
... | suc y = next (record { varx = suc (varx env) ; vary = y })
→ t で Set に遷移させるようにし、この後に関数が続くことと、関数を tail call していることで Continuation を定義している
Gears Agda と Gears CbC の対応 x
証明のしやすいGears Agda で実装を行いながらContext単位で同時に検証も行う
Gears Agda は検証向きの実装となり、CbCでは高速な実行向きとなる
Gears Agda での検証がCbCによる高速な実行の信頼性となる
Normal level と Meta Level を用いた信頼性の向上
CbCのプログラムの実行部分は以下の2つから構成される
Normal Level は軽量継続で関数型プログラミングとなる
ポインタの操作はここでは行わず Meta Level にて行う
Meta Level では信頼性を保証するために必要な計算を行う
メモリやCPUなどの資源管理
context
証明
並列実行(他のプロセスとの干渉)
monad
Gears Agda と Hoare Logic
C.A.R Hoare, R.W Floyd が考案
Pre Condition → Command → Post Condition
Gears Agda による Command の例
{-# TERMINATING #-}
whileLoop : {l : Level} {t : Set l} → Env → (Code : Env → t) → t
whileLoop env next with lt 0 (varn env)
whileLoop env next | false = next env
whileLoop env next | true = whileLoop (record {varn = (varn env) - 1 ; vari = (vari env) + 1}) next
{-# TERMINATING #-}
with 文
型と値
Gears Agda による検証の例(検証付き実装)
先ほど実装した while program に対して証明を付ける
loop を接続する Meta Gear も用意する
TerminatingLoopS : {l : Level} {t : Set l} ( Index : Set )
→ {Invraiant : Index → Set } → ( reduce : Index → N)
→ (loop : (r : Index) → Invraiant r
→ (next : (r1 : Index) → Invraiant r1 → reduce r1 < reduce r → t ) → t)
→ (r : Index) → (p : Invraiant r) → t
入力として仕様の証明を受け取る
出力として次の関数に仕様の証明を渡す
Hoare Conditionがプログラムの開始から停止するまで接続されていれば証明は完成
Meta Gear にて証明を値としてあたえているため
test との違い
test では実数を与えた際の出力が仕様に沿ったものであるかを検証する
コーナーケースで仕様に沿った動きをしていない場合を考慮できない
今回の定理証明を用いた証明では実数を必要としない
そのため、入力の型の範囲全てに対して仕様を満たしているか検証できる
Gears Agda による BinaryTree の実装
Agdaが変数への再代入を許していないためそのままでは木構造を実装できない
木構造を辿る際に現在いるノード以下の木構造をそのまま stack に格納する
replace / delete などの操作を行った後に stack を参照し Tree を再構築する
CbCへの変換の時に問題になりそうな予感
ここの説明いらないかも?
Gears Agda による BinaryTree の実装 find node
find : {n m : Level} {A : Set n} {t : Set m} → (env : Env A )
→ (next : (env : Env A ) → t ) → (exit : (env : Env A ) → t ) → t
find key leaf st _ exit = exit leaf st
find key (node key₁ v1 tree tree₁) st next exit with <-cmp key key₁
find key n st _ exit | tri≈ ¬a b ¬c = exit n st
find key n@(node key₁ v1 tree tree₁) st next _ | tri< a ¬b ¬c = next tree (n ∷ st)
find key n@(node key₁ v1 tree tree₁) st next _ | tri> ¬a ¬b c = next tree₁ (n ∷ st)
Gears Agda による BinaryTree の実装 replace node
replace : {n m : Level} {A : Set n} {t : Set m}
→ (key : N) → (value : A) → bt A → List (bt A)
→ (next : N → A → bt A → List (bt A) → t )
→ (exit : bt A → t) → t
replace key value repl [] next exit = exit repl -- can't happen
replace key value repl (leaf ∷ []) next exit = exit repl
replace key value repl (node key₁ value₁ left right ∷ []) next exit with <-cmp key key₁
... | tri< a ¬b ¬c = exit (node key₁ value₁ repl right )
... | tri≈ ¬a b ¬c = exit (node key₁ value left right )
... | tri> ¬a ¬b c = exit (node key₁ value₁ left repl )
replace key value repl (leaf ∷ st) next exit = next key value repl st
replace key value repl (node key₁ value₁ left right ∷ st) next exit with <-cmp key key₁
... | tri< a ¬b ¬c = next key value (node key₁ value₁ repl right ) st
... | tri≈ ¬a b ¬c = next key value (node key₁ value left right ) st
... | tri> ¬a ¬b c = next key value (node key₁ value₁ left repl ) st
Gears Agda による BinaryTree の実装 loop connecter
Gears Agda による Binary Tree の検証 Invariant
具体的な例を一つ挙げて、Invariantの説明を行う
Binary Tree の性質である、左の子のkeyは親より小さく、
右の子のkeyは親より大きいことを検証
data stackInvariant {n : Level} {A : Set n} (key : N) : (top orig : bt A)
→ (stack : List (bt A)) → Set n where
s-single : {tree0 : bt A} → stackInvariant key tree0 tree0 (tree0 ∷ [])
s-right : {tree tree0 tree₁ : bt A} → {key₁ : N } → {v1 : A } → {st : List (bt A)}
→ key₁ < key → stackInvariant key (node key₁ v1 tree₁ tree) tree0 st
→ stackInvariant key tree tree0 (tree ∷ st)
s-left : {tree₁ tree0 tree : bt A} → {key₁ : N } → {v1 : A } → {st : List (bt A)}
→ key < key₁ → stackInvariant key (node key₁ v1 tree₁ tree) tree0 st
→ stackInvariant key tree₁ tree0 (tree₁ ∷ st)
Gears Agda による Binary Tree の検証 Invariant
Replace Invariant
data replacedTree {n : Level} {A : Set n} (key : N) (value : A) : (before after : bt A) → Set n where
r-leaf : replacedTree key value leaf (node key value leaf leaf)
r-node : {value₁ : A} → {t t₁ : bt A}
→ replacedTree key value (node key value₁ t t₁) (node key value t t₁)
r-right : {k : N } {v1 : A} → {t t1 t2 : bt A}
→ k < key → replacedTree key value t2 t
→ replacedTree key value (node k v1 t1 t2) (node k v1 t1 t)
r-left : {k : N } {v1 : A} → {t t1 t2 : bt A}
→ key < k → replacedTree key value t1 t
→ replacedTree key value (node k v1 t1 t2) (node k v1 t t2)
Gears Agda による Binary Tree の検証
Binary Tree の実装に対して上述した3つのInvariantを
Meta Data Gear として渡しながら実行できるように記述する
findP : {n m : Level} {A : Set n} {t : Set m} → (env : Env A)
→ treeInvariant env ∧ stackInvariant env
→ (exit : (env : Env A) → treeInvariant env ∧ stackInvariant env → t ) → t
今後の研究方針
現在は Binary Tree の検証までしか行えていないが、
今回定義した条件はそのまま Red Black Tree の検証に使用できるはず
今後は Gears Agda による実装と条件の追加をおこなう
モデル検査
まとめ
Gears Agda にて Binary Tree を検証することができた
Gears Agda における Termination を使用しない実装の仕方を確率した
Hoare Logic による検証もできるようになった
今後は Red Black Tree の検証をすすめる
モデル検査をしたい
英語版も欲しい
condition を テンプレみたいに作ってかきやすくする話
研究目的
コードの解説
あとで…
findは全部書いても大丈夫そう
これは途中省略してよさそう
コードの解説
省略した方がたぶん絶対良い
right と left なんかはほとんど対照的なので省略とかでよさそう
あとは、木構造の仕様を満たすためにData型になっている説明があるとよさそう