Mercurial > hg > Papers > 2021 > soto-prosym
view slide/slide.md @ 10:60d4617eac84
fix slide intro
author | soto <soto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 06 Jan 2022 13:59:12 +0900 |
parents | e02e29a614c9 |
children | 8a97e69f8615 |
line wrap: on
line source
--- marp: true title: Geas Agda による Left Learning Red Black Tree の検証 paginate: true theme: default size: 16:9 style: | section { background-color: #FFFFFF; font-size: 28px; color: #4b4b4b; font-family: "Droid Sans Mono", "Hiragino Maru Gothic ProN"; background-image: url("logo.svg"); background-position: right 3% bottom 2%; background-repeat: no-repeat; background-attachment: 5%; background-size: 20% auto; } section.title h1 { color: #808db5; text-align: center; } section.title p { bottom: 25%; width: 100%; position: absolute; font-size: 25px; color: #4b4b4b; background: linear-gradient(transparent 90%, #ffcc00 0%); } section.slide h1 { width: 95%; color: white; background-color: #808db5; position: absolute; left: 50px; top: 35px; } section.fig_cg p { top: 300px; text-align: center; } --- <!-- headingDivider: 1 --> # Gears Agda による <br> Left Learning Red Black Tree の検証 <!-- class: title --> Uechi Yuto, Shinji Kono 琉球大学 # 証明を用いてプログラムの信頼性の向上を目指す <!-- class: slide --> <!-- 研究目的 --> - プログラムの信頼性を高めることは重要な課題である - 信頼性を高める手法として「モデル検査」や「定理証明」など - 当研究室でCbCという言語を開発している - C言語からループ構造とサブルーチンを取り除き、継続を導入したC言語の下位言語となる - 先行研究では Hoare Logic を用いて 簡単なプログラムの検証を行った - 本研究では Gears Agda にて重要なアルゴリズムの一つである Red Black Tree を検証する # CbC について - CbCとは当研究室で開発しているC言語の下位言語 - CbC とは C 言語からループ制御構造とサブルーチンコールを取り除き、継続を導入したC 言語の下位言語 - 継続呼び出しは引数付き goto 文で表現される。 - 処理の単位を Code Gear, データの単位を Data Gear として記述するプログラミング言語 - CbC のプログラミングでは Data Gear を Code Gear で変更し、その変更を次の Code Gear に渡して処理を行う。 # Agda の基本 - Agdaとは定理証明支援器であり、関数型言語である - Agdaでの関数は、最初に型について定義した後に、関数を定義する事で記述できる - これが Curry-Howard 対応となる - 型の定義部分で、入力と出力の型を定義できる - input → output のようになる - 関数の定義は = を用いて行う - 関数名の後、 = の前で受け取る引数を記述します ``` sample1 : (A : Set ) → Set sample1 a = a sample2 : (A : Set ) → (B : Set ) → Set sample2 a b = b ``` # Agda の基本 record - 2つのものが同時に存在すること - Record 型とはオブジェクトあるいは構造体 ``` record Env : Set where field varn : N vari : N open Env ``` 型に対応する値の導入(intro) ``` record {varx = zero ; vary = suc zero} ``` record の値のアクセス(elim) ``` (env : Env) → varx env ``` # Gears Agda の記法 Gears Agda では CbC と対応させるためにすべてLoopで記述する loopは`→ t`の形式で表現する 再起呼び出しは使わない(構文的には禁止していないので注意が必要) ``` {-# 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 ``` - t を返すで継続を表す(tは呼び出し時に任意に指定してもよい. testに使える) - tail call により light weight continuation を定義している # Gears Agda と Gears CbC の対応 Gears Agda - 証明向きの記述 - Hoare Condition を含む Gears CbC - 実行向きの記述 - メモリ管理, 並列実行を含む Context - processに相当する - Code Gear 単位で並列実行 # Normal level と Meta Level を用いた信頼性の向上 Normal Level - 軽量継続 - Code Gear 単位で関数型プログラミングとなる - atomic(Code Gear 自体の実行は割り込まれない) - ポインタの操作は含まれない Meta Level - メモリやCPUなどの資源管理, ポインタ操作 - Hoare Condition と証明 - Contextによる並列実行 - monadに相当するData構造 # <!-- class: fig_cg --> ![height:700px](meta_cg_dg.svg) # Gears Agda と Hoare Logic <!-- class: slide --> 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 の Pre Condition Post Condition ``` whileLoopSeg : {l : Level} {t : Set l} → {c10 : N } → (env : Env) → (varn env + vari env ≡ c10) → (next : (e1 : Env )→ varn e1 + vari e1 ≡ c10 → varn e1 < varn env → t) → (exit : (e1 : Env )→ vari e1 ≡ c10 → t) → t ``` - Terminatingを避けるためにloopを分割 - `varn env + vari env ≡ c10` が Pre Condition - `varn e1 + vari e1 ≡ c10` が Post Condition - `varn e1 < varn env → t` が停止を保証する減少列 これは命題なので証明を与えてPre ConditionからPost Conditionを導出する必要がある 証明は値として次のCodeGearに渡される # Loop の接続 分割したloopを接続するMeta Code 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 ``` - IndexはLoop変数 - Invariantはloop変数の不変条件 - loopに接続するCode Gearを与える - reduceは停止性を保証する減少列 これを一般的に証明することができている # 実際のloopの接続 証明したい性質を以下のように記述する ``` whileTestSpec1 : (c10 : N) → (e1 : Env ) → vari e1 ≡ c10 → ⊤ whileTestSpec1 _ _ x = tt ``` loopをTerminatingLoopSで接続して仕様記述に繋げる ``` proofGearsTermS : {c10 : N} → ⊤ proofGearsTermS {c10} = whileTest' {_} {_} {c10} (λ n p → conversion1 n p (λ n1 p1 → TerminatingLoopS Env (λ env → varn env)(λ n2 p2 loop → whileLoopSeg {_} {_} {c10} n2 p2 loop (λ ne pe → whileTestSpec1 c10 ne pe)) n1 p1 )) ``` - conversion1は - whileLoopSeg - ⊤ # 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) ``` <!-- findは全部書いても大丈夫そう --> # 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は親より大きいことを検証 - Stack に格納されているTreeはその次のStackの減少列になっているか - Tree を正しく入れ替えられているか # Gears Agda による Binary Tree の検証 Invariant - Tree Invariant ``` data treeInvariant {n : Level} {A : Set n} : (tree : bt A) → Set n where t-leaf : treeInvariant leaf t-single : (key : N) → (value : A) → treeInvariant (node key value leaf leaf) t-right : {key key₁ : N} → {value value₁ : A} → {t₁ t₂ : bt A} → (key < key₁) → treeInvariant (node key₁ value₁ t₁ t₂) → treeInvariant (node key value leaf (node key₁ value₁ t₁ t₂)) t-left : {key key₁ : N} → {value value₁ : A} → {t₁ t₂ : bt A} → (key < key₁) → treeInvariant (node key value t₁ t₂) → treeInvariant (node key₁ value₁ (node key value t₁ t₂) leaf ) t-node : {key key₁ key₂ : N} → {value value₁ value₂ : A} → {t₁ t₂ t₃ t₄ : bt A} → (key < key₁) → (key₁ < key₂) → treeInvariant (node key value t₁ t₂) → treeInvariant (node key₂ value₂ t₃ t₄) → treeInvariant (node key₁ value₁ (node key value t₁ t₂) (node key₂ value₂ t₃ t₄)) ``` <!-- コードの解説 省略した方がたぶん絶対良い right と left なんかはほとんど対照的なので省略とかでよさそう あとは、木構造の仕様を満たすためにData型になっている説明があるとよさそう --> # Gears Agda による Binary Tree の検証 Invariant - Stack Invariant ``` 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 を テンプレみたいに作ってかきやすくする話