diff options
author | Raito Bezarius | 2024-04-04 17:31:19 +0200 |
---|---|---|
committer | Raito Bezarius | 2024-04-05 18:33:47 +0200 |
commit | 50be416e22a39eaf59f7edba81b919e1f114a0ae (patch) | |
tree | 255447dcbbf7d26233b2caa092dc1af9ce188f2b | |
parent | 22a499f5d4d231bef3193405983f9ade6da116db (diff) |
feat: close the BST proof modulo unbundling
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
-rw-r--r-- | AvlVerification/Insert.lean | 51 | ||||
-rw-r--r-- | AvlVerification/Specifications.lean | 10 |
2 files changed, 60 insertions, 1 deletions
diff --git a/AvlVerification/Insert.lean b/AvlVerification/Insert.lean index 92691b2..3c2b8b3 100644 --- a/AvlVerification/Insert.lean +++ b/AvlVerification/Insert.lean @@ -7,8 +7,16 @@ namespace Implementation open Primitives open avl_verification open Tree (AVLTree) +open Specifications (OrdSpec ordSpecOfInfaillible ordOfOrdSpec ltOfRustOrder) -variable {T: Type} +-- TODO: OSpec should be proven. +variable (T: Type) (H: avl_verification.Ord T) (Ospec: @OrdSpec T H) + +instance rustOrder {U: Type} {O: avl_verification.Ord U} (OSpec: OrdSpec O): _root_.Ord U := ordOfOrdSpec O OSpec +-- Why the TC fails if I don't specify the previous instance explicitly? +instance rustLt {U: Type} {O: avl_verification.Ord U} (OSpec: OrdSpec O): LT U := @ltOfOrd _ (ordOfOrdSpec O OSpec) + +instance rustLt' : LT T := rustLt Ospec @[pspec] theorem AVLTreeSet.insert_loop_spec_local (p: T -> Prop) @@ -55,6 +63,47 @@ theorem AVLTreeSet.insert_loop_spec_local (p: T -> Prop) exact Hptree.right } +@[pspec] +lemma AVLTreeSet.insert_loop_spec_global + (a: T) (t: Option (AVLNode T)) + : + haveI : LT T := (rustLt Ospec) + BST.BST t -> ∃ added t_new, AVLTreeSet.insert_loop T H a t = Result.ret ⟨ added, t_new ⟩ + ∧ BST.BST t_new := by + intro Hbst + letI instOrd : _root_.Ord T := (rustOrder Ospec) + letI instLt : LT T := (rustLt Ospec) + match t with + | none => simp [AVLTreeSet.insert_loop] + | some (AVLNode.mk b left right) => + rw [AVLTreeSet.insert_loop] + simp only [] + have := Ospec.infallible; simp at this + -- TODO: unbundle `this`... + have : ∀ a b, ∃ o, H.cmp a b = .ret o := sorry + progress keep Hordering as ⟨ ordering ⟩ + cases ordering + all_goals simp only [] + { + have ⟨ added₂, right₂, ⟨ H_result, H_bst ⟩ ⟩ := AVLTreeSet.insert_loop_spec_global a right (BST.right Hbst) + progress keep Htree with AVLTreeSet.insert_loop_spec_local as ⟨ added₁, right₁, Hnode ⟩ + exact (fun x => b < x) + rewrite [Htree] at H_result; simp at H_result + refine' ⟨ added₁, ⟨ some (AVLNode.mk b left right₁), _ ⟩ ⟩ + simp only [true_and] + cases' Hbst with _ _ _ H_forall_left H_forall_right H_bst_left H_bst_right + constructor + exact H_forall_left + apply Hnode; exact H_forall_right + exact (ltOfRustOrder H b a Hordering) + exact H_bst_left + convert H_bst + exact H_result.2 + } + { + simp; tauto + } + { sorry } diff --git a/AvlVerification/Specifications.lean b/AvlVerification/Specifications.lean index 94fdd5f..247fd00 100644 --- a/AvlVerification/Specifications.lean +++ b/AvlVerification/Specifications.lean @@ -67,4 +67,14 @@ def ordOfOrdSpec (H: avl_verification.Ord T) (spec: OrdSpec H): Ord T where simp only ) +theorem ltOfRustOrder {Spec: OrdSpec H}: + haveI O := ordOfOrdSpec H Spec + haveI := @ltOfOrd _ O + ∀ a b, H.cmp a b = .ret .Less -> a < b := by + intros a b + intro Hcmp + change ((Spec.cmp a b).get? _ == .lt) + simp [Hcmp, map, avl_verification.Ordering.toLeanOrdering] + simp [get?] + rfl end Specifications |