{-# OPTIONS --rewriting #-}
module Examples.Amortized.SplayTree.SplayTree where
open import Algebra.Cost
costMonoid = ℕ-CostMonoid
open CostMonoid costMonoid renaming (_+_ to _⊕_)
open import Calf costMonoid
open import Calf.Data.List hiding (find)
open import Calf.Data.Nat
open import Calf.Data.Bool as Bool using (bool; true; false)
open import Calf.Data.Product
open import Data.Nat as Nat using (ℕ; _<_; _≤?_; _<?_; zero)
open import Data.Nat.Properties as Nat using (module ≤-Reasoning; _≟_)
open import Data.Bool.Properties as Bool
open import Data.List.Properties as List
open import Relation.Binary
open import Relation.Binary.PropositionalEquality as Eq using (_≡_; _≢_; refl; module ≡-Reasoning)
open import Data.Empty using (⊥; ⊥-elim)
open import Examples.Amortized.SplayTree.Base
data Tree : Set where
leaf : Tree
node : Tree → val nat → Tree → Tree
tree : tp⁺
tree = meta⁺ Tree
tree-size : Tree → val nat
tree-size leaf = 0
tree-size (node l z r) = (tree-size l) + 1 + (tree-size r)
inord : Tree → val (list nat)
inord leaf = []
inord (node l z r) = inord l ++ z ∷ [] ++ inord r
data Context : Set where
Left : (k : val nat) (t : Tree) → Context
Right : (t : Tree) (k : val nat) → Context
context : tp⁺
context = meta⁺ (Context)
searchType : tp⁺
searchType = bool ×⁺ tree ×⁺ (list context)
reconstruct : (t : Tree) (anc : List Context) → Tree
reconstruct t [] = t
reconstruct t (Left x r ∷ anc') = reconstruct (node t x r) anc'
reconstruct t (Right l x ∷ anc') = reconstruct (node l x t) anc'
inord/reconstruct : (t₁ t₂ : Tree) (anc : List Context) → inord t₁ ≡ inord t₂ →
inord (reconstruct t₁ anc) ≡ inord (reconstruct t₂ anc)
inord/reconstruct t₁ t₂ [] t₁≡t₂ = t₁≡t₂
inord/reconstruct t₁ t₂ (Left k t ∷ anc) t₁≡t₂ =
inord/reconstruct (node t₁ k t) (node t₂ k t) anc
(Eq.cong (λ e → e ++ (k ∷ inord t)) t₁≡t₂)
inord/reconstruct t₁ t₂ (Right t k ∷ anc) t₁≡t₂ =
inord/reconstruct (node t k t₁) (node t k t₂) anc
(Eq.cong (λ e → inord t ++ e) (Eq.cong (λ e → k ∷ e) t₁≡t₂))
root : (t : Tree) → val nat
root leaf = 0
root (node l x r) = x
size>0 : (a : Tree) (z : val nat) (b : Tree) → tree-size (node a z b) > 0
size>0 a z b = let open Nat.≤-Reasoning in
begin
1
≤⟨ Nat.m≤m+n 1 (tree-size a + tree-size b) ⟩
1 + (tree-size a + tree-size b)
≡⟨ Nat.+-assoc 1 (tree-size a) (tree-size b) ⟨
(1 + tree-size a) + tree-size b
≡⟨ Eq.cong (λ e → e + tree-size b) (Nat.+-comm 1 (tree-size a)) ⟩
(tree-size a + 1) + tree-size b
∎
searchInordType : Tree → val nat → List Context → tp⁺
searchInordType t k anc = Σ⁺ searchType (λ (b , t' , anc') →
(meta⁺ (reconstruct t anc ≡ reconstruct t' anc')) ×⁺
meta⁺ ((b ≡ true) → 0 < tree-size t') ×⁺
meta⁺ ((b ≡ true) → root t' ≡ k))
search : (t : Tree) (k : val nat) (anc : List Context) → val (searchInordType t k anc)
search leaf k anc =
(((false , leaf , anc) , refl , (λ x → ⊥-elim (Bool.<-irrefl x Bool.f<t)) , λ x → ⊥-elim (Bool.<-irrefl x Bool.f<t)))
search (node l x r) k anc with Nat.<-cmp k x
... | tri< _ _ _ = search l k (Left x r ∷ anc)
... | tri≈ _ k≡x _ =
(((true , node l x r , anc) , refl , (λ _ → size>0 l x r) , λ _ → Eq.sym k≡x))
... | tri> _ _ _ = search r k (Right l x ∷ anc)
splay'ResultType : val nat → Tree → Tree → List Context → tp⁺
splay'ResultType k a b anc = Σ⁺ (tree ×⁺ tree) (λ (a' , b') →
meta⁺ (inord (reconstruct (node a k b) anc) ≡ inord (node a' k b')))
zig/zig/arithmetic : (l₁ l₂ l₃ l₄ : val (list nat)) → ((l₁ ++ l₂) ++ l₃) ++ l₄ ≡ l₁ ++ l₂ ++ l₃ ++ l₄
zig/zig/arithmetic l₁ l₂ l₃ l₄ =
let open ≡-Reasoning in
begin
((l₁ ++ l₂) ++ l₃) ++ l₄
≡⟨ ++-assoc (l₁ ++ l₂) l₃ l₄ ⟩
(l₁ ++ l₂) ++ (l₃ ++ l₄)
≡⟨ ++-assoc l₁ l₂ (l₃ ++ l₄) ⟩
l₁ ++ (l₂ ++ (l₃ ++ l₄))
∎
zig/zig/inord/arith : (a b c d : Tree) (k p g : val nat) →
inord (node (node (node a k b) p c) g d) ≡ inord (node a k (node b p (node c g d)))
zig/zig/inord/arith a b c d k p g = zig/zig/arithmetic (inord a) (k ∷ inord b) (p ∷ inord c) (g ∷ inord d)
zig/zag/arithmetic : (l₁ l₂ l₃ l₄ : val (list nat)) → (l₁ ++ l₂ ++ l₃) ++ l₄ ≡ (l₁ ++ l₂) ++ l₃ ++ l₄
zig/zag/arithmetic l₁ l₂ l₃ l₄ =
let open ≡-Reasoning in
begin
(l₁ ++ (l₂ ++ l₃)) ++ l₄
≡⟨ Eq.cong (λ e → e ++ l₄) (++-assoc l₁ l₂ l₃) ⟨
((l₁ ++ l₂) ++ l₃) ++ l₄
≡⟨ ++-assoc (l₁ ++ l₂) l₃ l₄ ⟩
(l₁ ++ l₂) ++ l₃ ++ l₄
∎
zig/zag/inord/arith : (a b c d : Tree) (k p g : val nat) →
inord (node (node a p (node b k c)) g d) ≡ inord (node (node a p b) k (node c g d))
zig/zag/inord/arith a b c d k p g = zig/zag/arithmetic (inord a) (p ∷ inord b) (k ∷ inord c) (g ∷ inord d)
zag/zag/arithmetic : (l₁ l₂ l₃ l₄ : val (list nat)) → l₁ ++ l₂ ++ l₃ ++ l₄ ≡ ((l₁ ++ l₂) ++ l₃) ++ l₄
zag/zag/arithmetic l₁ l₂ l₃ l₄ =
let open ≡-Reasoning in
begin
l₁ ++ (l₂ ++ (l₃ ++ l₄))
≡⟨ ++-assoc l₁ l₂ (l₃ ++ l₄) ⟨
(l₁ ++ l₂) ++ (l₃ ++ l₄)
≡⟨ ++-assoc (l₁ ++ l₂) l₃ l₄ ⟨
((l₁ ++ l₂) ++ l₃) ++ l₄
∎
zag/zag/inord/arith : (a b c d : Tree) (k p g : val nat) →
inord (node a g (node b p (node c k d))) ≡ inord (node (node (node a g b) p c) k d)
zag/zag/inord/arith a b c d k p g = zag/zag/arithmetic (inord a) (g ∷ inord b) (p ∷ inord c) (k ∷ inord d)
zag/zig/arithmetic : (l₁ l₂ l₃ l₄ : val (list nat)) → l₁ ++ (l₂ ++ l₃) ++ l₄ ≡ (l₁ ++ l₂) ++ l₃ ++ l₄
zag/zig/arithmetic l₁ l₂ l₃ l₄ =
let open ≡-Reasoning in
begin
l₁ ++ (l₂ ++ l₃) ++ l₄
≡⟨ ++-assoc l₁ (l₂ ++ l₃) l₄ ⟨
(l₁ ++ (l₂ ++ l₃)) ++ l₄
≡⟨ Eq.cong (λ e → e ++ l₄) (++-assoc l₁ l₂ l₃) ⟨
((l₁ ++ l₂) ++ l₃) ++ l₄
≡⟨ ++-assoc (l₁ ++ l₂) l₃ l₄ ⟩
(l₁ ++ l₂) ++ l₃ ++ l₄
∎
zag/zig/inord/arith : (a b c d : Tree) (k p g : val nat) →
inord (node a g (node (node b k c) p d)) ≡ inord (node (node a g b) k (node c p d))
zag/zig/inord/arith a b c d k p g = zag/zig/arithmetic (inord a) (g ∷ inord b) (k ∷ inord c) (p ∷ inord d)
splay' : (a : Tree) (b : Tree) (anc : List Context) (k : val nat) → cmp (F (splay'ResultType k a b anc))
splay' a b [] k = ret ((a , b) , refl)
splay' a b (Left p c ∷ []) k =
step (F _) 1 (
ret ((a , node b p c) , ++-assoc (inord a) (k ∷ inord b) (p ∷ inord c)))
splay' b c (Right a p ∷ []) k =
step (F _) 1 (
ret ((node a p b , c) , arithmetic (inord a) (p ∷ inord b) (k ∷ inord c)))
where
arithmetic : (l₁ l₂ l₃ : val (list nat)) → l₁ ++ l₂ ++ l₃ ≡ (l₁ ++ l₂) ++ l₃
arithmetic l₁ l₂ l₃ = Eq.sym (++-assoc l₁ l₂ l₃)
splay' a b (Left p c ∷ Left g d ∷ anc) k =
step (F _) 1 (
bind (F _) (splay' a (node b p (node c g d)) anc k) (λ ((l' , r') , recon≡inord) →
ret ((l' , r') , Eq.trans (inord/reconstruct
(node (node (node a k b) p c) g d)
(node a k (node b p (node c g d)))
anc
(zig/zig/inord/arith a b c d k p g)) recon≡inord)))
splay' b c (Left p d ∷ Right a g ∷ anc) k =
step (F _) 1 (
bind (F _) (splay' (node a g b) (node c p d) anc k) (λ ((l' , r') , recon≡inord) →
ret ((l' , r') , Eq.trans (inord/reconstruct
(node a g (node (node b k c) p d))
(node (node a g b) k (node c p d))
anc
(zag/zig/inord/arith a b c d k p g)) recon≡inord)))
splay' b c (Right a p ∷ Left g d ∷ anc) k =
step (F _) 1 (
bind (F _) (splay' (node a p b) (node c g d) anc k) (λ ((l' , r') , recon≡inord) →
ret ((l' , r') , Eq.trans (inord/reconstruct
(node (node a p (node b k c)) g d)
(node (node a p b) k (node c g d))
anc
(zig/zag/inord/arith a b c d k p g)) recon≡inord)))
splay' c d (Right b p ∷ Right a g ∷ anc) k =
step (F _) 1 (
bind (F _) (splay' (node (node a g b) p c) d anc k) (λ ((l' , r') , recon≡inord) →
ret ((l' , r') , Eq.trans (inord/reconstruct
(node a g (node b p (node c k d)))
(node (node (node a g b) p c) k d)
anc
(zag/zag/inord/arith a b c d k p g)) recon≡inord)))
makeTree/nodups/sorted : (t : Tree) (l : val (list nat)) → val (tree)
makeTree/nodups/sorted t [] = t
makeTree/nodups/sorted t (k ∷ ks) = makeTree/nodups/sorted (node t k leaf) ks
SplayTree : BST
SplayTree .BST.T = tree
SplayTree .BST.fromList l = ret (makeTree/nodups/sorted leaf (sort/val (deduplicate {R = _≡_} Nat._≟_ l)))
SplayTree .BST.size t = ret (tree-size t)
SplayTree .BST.find t k with (search t k [])
... | ((false , t' , anc) , _ , _ , _) = ret (false , t)
... | ((true , leaf , anc) , _ , 0<0 , _) = ⊥-elim (Nat.<-irrefl refl (0<0 refl))
... | ((true , node l x r , anc) , _ , _ , _) =
bind (F _) (splay' l r anc k) (λ ((l' , r') , _) → ret (true , node l' x r'))