diff --git a/src/Examples.agda b/src/Examples.agda
index 0a7a63e1..62e0c835 100644
--- a/src/Examples.agda
+++ b/src/Examples.agda
@@ -16,5 +16,8 @@ import Examples.Exp2
-- Amortized Analysis via Coinduction
import Examples.Amortized
+-- Sequence
+import Examples.Sequence
+
-- Effectful
import Examples.Decalf
diff --git a/src/Examples/Sequence.agda b/src/Examples/Sequence.agda
new file mode 100644
index 00000000..43c09024
--- /dev/null
+++ b/src/Examples/Sequence.agda
@@ -0,0 +1,219 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+open import Calf.Parallel parCostMonoid
+
+open import Calf.Data.Product
+open import Calf.Data.Sum
+open import Calf.Data.Bool
+open import Calf.Data.Maybe
+open import Calf.Data.Nat hiding (compare)
+open import Calf.Data.List hiding (filter)
+
+open import Level using (0ℓ)
+open import Relation.Binary
+open import Data.Nat as Nat using (_<_; _+_)
+import Data.Nat.Properties as Nat
+open import Data.String using (String)
+open import Relation.Binary.PropositionalEquality as Eq using (_≡_)
+
+open import Function using (case_of_; _$_)
+
+open import Examples.Sequence.MSequence
+open import Examples.Sequence.ListMSequence
+open import Examples.Sequence.RedBlackMSequence
+
+
+module Ex/FromList where
+ open MSequence RedBlackMSequence
+
+ fromList : cmp (Π (list nat) λ _ → F (seq nat))
+ fromList [] = empty
+ fromList (x ∷ l) =
+ bind (F (seq nat)) empty λ s₁ →
+ bind (F (seq nat)) (fromList l) λ s₂ →
+ join s₁ x s₂
+
+ example : cmp (F (seq nat))
+ example = fromList (1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ [])
+
+
+module BinarySearchTree
+ (MSeq : MSequence)
+ (Key : StrictTotalOrder 0ℓ 0ℓ 0ℓ)
+ where
+
+ open StrictTotalOrder Key
+
+ 𝕂 : tp⁺
+ 𝕂 = meta⁺ (StrictTotalOrder.Carrier Key)
+
+ open MSequence MSeq public
+
+ singleton : cmp (Π 𝕂 λ _ → F (seq 𝕂))
+ singleton a =
+ bind (F (seq 𝕂)) empty λ t →
+ join t a t
+
+ Split : tp⁻
+ Split = F ((seq 𝕂) ×⁺ ((maybe 𝕂) ×⁺ (seq 𝕂)))
+
+ split : cmp (Π (seq 𝕂) λ _ → Π 𝕂 λ _ → Split)
+ split t a =
+ rec
+ {X = Split}
+ (bind Split empty λ t →
+ ret (t , nothing , t))
+ (λ t₁ ih₁ a' t₂ ih₂ →
+ case compare a a' of λ
+ { (tri< aa') →
+ bind Split ih₁ λ ( t₁₁ , a? , t₁₂ ) →
+ bind Split (join t₁₂ a' t₂) λ t →
+ ret (t₁₁ , a? , t)
+ ; (tri≈ ¬aa') → ret (t₁ , just a' , t₂)
+ ; (tri> ¬aa') →
+ bind Split ih₂ λ ( t₂₁ , a? , t₂₂ ) →
+ bind Split (join t₁ a' t₂₁) λ t →
+ ret (t , a? , t₂₂)
+ })
+ t
+
+ find : cmp (Π (seq 𝕂) λ _ → Π 𝕂 λ _ → F (maybe 𝕂))
+ find t a = bind (F (maybe 𝕂)) (split t a) λ { (_ , a? , _) → ret a? }
+
+ insert : cmp (Π (seq 𝕂) λ _ → Π 𝕂 λ _ → F (seq 𝕂))
+ insert t a = bind (F (seq 𝕂)) (split t a) λ { (t₁ , _ , t₂) → join t₁ a t₂ }
+
+ append : cmp (Π (seq 𝕂) λ _ → Π (seq 𝕂) λ _ → F (seq 𝕂))
+ append t₁ t₂ =
+ rec
+ {X = F (seq 𝕂)}
+ (ret t₂)
+ (λ t'₁ ih₁ a' t'₂ ih₂ →
+ bind (F (seq 𝕂)) ih₂ λ t' →
+ join t'₁ a' t')
+ t₁
+
+ delete : cmp (Π (seq 𝕂) λ _ → Π 𝕂 λ _ → F (seq 𝕂))
+ delete t a = bind (F (seq 𝕂)) (split t a) λ { (t₁ , _ , t₂) → append t₁ t₂ }
+
+ union : cmp (Π (seq 𝕂) λ _ → Π (seq 𝕂) λ _ → F (seq 𝕂))
+ union =
+ rec
+ {X = Π (seq 𝕂) λ _ → F (seq 𝕂)}
+ ret
+ λ t'₁ ih₁ a' t'₂ ih₂ t₂ →
+ bind (F (seq 𝕂)) (split t₂ a') λ { (t₂₁ , a? , t₂₂) →
+ bind (F (seq 𝕂)) ((ih₁ t₂₁) ∥ (ih₂ t₂₂)) λ (s₁ , s₂) →
+ join s₁ a' s₂ }
+
+ intersection : cmp (Π (seq 𝕂) λ _ → Π (seq 𝕂) λ _ → F (seq 𝕂))
+ intersection =
+ rec
+ {X = Π (seq 𝕂) λ _ → F (seq 𝕂)}
+ (λ t₂ → empty)
+ λ t'₁ ih₁ a' t'₂ ih₂ t₂ →
+ bind (F (seq 𝕂)) (split t₂ a') λ { (t₂₁ , a? , t₂₂) →
+ bind (F (seq 𝕂)) ((ih₁ t₂₁) ∥ (ih₂ t₂₂)) λ (s₁ , s₂) →
+ case a? of
+ λ { (just a) → join s₁ a s₂
+ ; nothing → append s₁ s₂ }
+ }
+
+ difference : cmp (Π (seq 𝕂) λ _ → Π (seq 𝕂) λ _ → F (seq 𝕂))
+ difference t₁ t₂ = helper t₁
+ where
+ helper : cmp (Π (seq 𝕂) λ _ → F (seq 𝕂))
+ helper =
+ rec
+ {X = Π (seq 𝕂) λ _ → F (seq 𝕂)}
+ ret
+ (λ t'₁ ih₁ a' t'₂ ih₂ t₁ →
+ bind (F (seq 𝕂)) (split t₁ a') λ { (t₁₁ , a? , t₁₂) →
+ bind (F (seq 𝕂)) ((ih₁ t₁₁) ∥ (ih₂ t₁₂)) λ (s₁ , s₂) →
+ append s₁ s₂
+ })
+ t₂
+
+ filter : cmp (Π (seq 𝕂) λ _ → Π (U (Π 𝕂 λ _ → F bool)) λ _ → F (seq 𝕂))
+ filter t f =
+ rec
+ {X = F (seq 𝕂)}
+ (bind (F (seq 𝕂)) empty ret)
+ (λ t'₁ ih₁ a' t'₂ ih₂ →
+ bind (F (seq 𝕂)) (ih₁ ∥ ih₂) (λ (s₁ , s₂) →
+ bind (F (seq 𝕂)) (f a') λ b →
+ if b then (join s₁ a' s₂) else (append s₁ s₂)))
+ t
+
+ mapreduce : {X : tp⁻} →
+ cmp (
+ Π (seq 𝕂) λ _ →
+ Π (U (Π 𝕂 λ _ → X)) λ _ →
+ Π (U (Π (U X) λ _ → Π (U X) λ _ → X)) λ _ →
+ Π (U X) λ _ →
+ X
+ )
+ mapreduce {X} t g f l =
+ rec {X = X} l (λ t'₁ ih₁ a' t'₂ ih₂ → f ih₁ (f (g a') ih₂)) t
+
+
+module Ex/NatSet where
+ open BinarySearchTree RedBlackMSequence Nat.<-strictTotalOrder
+
+ example : cmp Split
+ example =
+ bind Split (singleton 1) λ t₁ →
+ bind Split (insert t₁ 2) λ t₁ →
+ bind Split (singleton 4) λ t₂ →
+ bind Split (join t₁ 3 t₂) λ t →
+ split t 2
+
+ sum/seq : cmp (Π (seq nat) λ _ → F (nat))
+ sum/seq =
+ rec
+ {X = F (nat)}
+ (ret 0)
+ λ t'₁ ih₁ a' t'₂ ih₂ →
+ step (F nat) (1 , 1) $
+ bind (F (nat)) (ih₁ ∥ ih₂)
+ (λ (s₁ , s₂) → ret (s₁ + a' + s₂))
+
+
+
+module Ex/NatStringDict where
+ strictTotalOrder : StrictTotalOrder 0ℓ 0ℓ 0ℓ
+ strictTotalOrder =
+ record
+ { Carrier = ℕ × String
+ ; _≈_ = λ (n₁ , _) (n₂ , _) → n₁ ≡ n₂
+ ; _<_ = λ (n₁ , _) (n₂ , _) → n₁ Nat.< n₂
+ ; isStrictTotalOrder =
+ record
+ { isEquivalence =
+ record
+ { refl = Eq.refl
+ ; sym = Eq.sym
+ ; trans = Eq.trans
+ }
+ ; trans = Nat.<-trans
+ ; compare = λ (n₁ , _) (n₂ , _) → Nat.<-cmp n₁ n₂
+ }
+ }
+
+ open BinarySearchTree RedBlackMSequence strictTotalOrder
+
+ example : cmp Split
+ example =
+ bind Split (singleton (1 , "red")) λ t₁ →
+ bind Split (insert t₁ (2 , "orange")) λ t₁ →
+ bind Split (singleton (4 , "green")) λ t₂ →
+ bind Split (join t₁ (3 , "yellow") t₂) λ t →
+ split t (2 , "")
diff --git a/src/Examples/Sequence/DerivedFormsRBT.agda b/src/Examples/Sequence/DerivedFormsRBT.agda
new file mode 100644
index 00000000..ff1197a2
--- /dev/null
+++ b/src/Examples/Sequence/DerivedFormsRBT.agda
@@ -0,0 +1,515 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence.DerivedFormsRBT where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+open import Calf.Parallel parCostMonoid
+
+open import Calf.Data.Nat
+open import Calf.Data.List
+open import Calf.Data.Product
+open import Calf.Data.IsBounded costMonoid
+open import Calf.Data.IsBoundedG costMonoid
+open import Data.List as List hiding (sum; map)
+import Data.List.Properties as List
+open import Data.Nat as Nat using (_+_; _*_)
+import Data.Nat.Properties as Nat
+open import Data.Nat.Logarithm
+
+open import Function using (_$_)
+open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl; module ≡-Reasoning)
+
+open import Examples.Sequence.RedBlackTree
+
+module _ {A : Set} where
+ list/preserves/length : ∀ (l₁ : List A) a (l₂ : List A) → 1 + (length l₁ + length l₂) ≡ length (l₁ ++ a ∷ l₂)
+ list/preserves/length l₁ a l₂ =
+ let open ≡-Reasoning in
+ begin
+ 1 + (length l₁ + length l₂)
+ ≡˘⟨ Nat.+-assoc 1 (length l₁) (length l₂) ⟩
+ 1 + length l₁ + length l₂
+ ≡⟨ Eq.cong₂ _+_ (Nat.+-comm 1 (length l₁)) refl ⟩
+ length l₁ + 1 + length l₂
+ ≡⟨ Nat.+-assoc (length l₁) 1 (length l₂) ⟩
+ length l₁ + (1 + length l₂)
+ ≡⟨⟩
+ length l₁ + length (a ∷ l₂)
+ ≡˘⟨ List.length-++ l₁ ⟩
+ length (l₁ ++ a ∷ l₂)
+ ∎
+
+ list/preserves/length' : ∀ (l₁ : List A) a (l₂ : List A) → (length l₁ + length l₂) + 1 ≡ length (l₁ ++ a ∷ l₂)
+ list/preserves/length' l₁ a l₂ =
+ let open ≡-Reasoning in
+ begin
+ (length l₁ + length l₂) + 1
+ ≡⟨ Nat.+-comm (length l₁ + length l₂) 1 ⟩
+ 1 + (length l₁ + length l₂)
+ ≡⟨ list/preserves/length l₁ a l₂ ⟩
+ length (l₁ ++ a ∷ l₂)
+ ∎
+
+
+module MapReduce {A B : tp⁺} where
+ mapreduce/seq : cmp $
+ Π color λ y → Π nat λ n → Π (list A) λ l → Π (irbt A y n l) λ _ →
+ Π (U (Π A λ _ → F B)) λ _ →
+ Π (U (Π B λ _ → Π B λ _ → F B)) λ _ →
+ Π B λ _ →
+ F B
+ mapreduce/seq .black .zero .[] leaf f g z = ret z
+ mapreduce/seq .red n l (red t₁ a t₂) f g z =
+ bind (F B)
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ s →
+ bind (F B) (f a) (λ b →
+ bind (F B) (g b (proj₂ s)) (λ s₃ →
+ bind (F B) (g (proj₁ s) s₃) ret))
+ mapreduce/seq .black n@(suc n') l (black t₁ a t₂) f g z =
+ bind (F B)
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ s →
+ bind (F B) (f a) (λ b →
+ bind (F B) (g b (proj₂ s)) (λ s₃ →
+ bind (F B) (g (proj₁ s) s₃) ret))
+
+ mapreduce/work : val nat → val nat → val (list A) → val nat
+ mapreduce/work c₁ c₂ l = (c₁ + 2 * c₂) * length l
+
+ mapreduce/span : val nat → val nat → val color → val nat → val nat
+ mapreduce/span c₁ c₂ red n = (2 * c₁ + 4 * c₂) * n + (c₁ + 2 * c₂)
+ mapreduce/span c₁ c₂ black n = (2 * c₁ + 4 * c₂) * n
+
+ mapreduce/span' : val nat → val nat → val nat → val nat
+ mapreduce/span' c₁ c₂ n = (2 * c₁ + 4 * c₂) * n + (c₁ + 2 * c₂)
+
+ span/bounded : (c₁ c₂ : val nat) → (y : val color) → (n : val nat) → mapreduce/span c₁ c₂ y n Nat.≤ mapreduce/span' c₁ c₂ n
+ span/bounded c₁ c₂ red n = Nat.≤-refl
+ span/bounded c₁ c₂ black n = Nat.m≤m+n ((2 * c₁ + 4 * c₂) * n) (c₁ + 2 * c₂)
+
+ mapreduce/is-bounded' :
+ {c₁ c₁' c₂ c₂' : val nat} →
+ (f : cmp (Π A λ _ → F B)) →
+ ({x : val A} → IsBounded B (f x) (c₁ , c₁')) →
+ (g : cmp (Π B λ _ → Π B λ _ → F B)) →
+ ({x y : val B} → IsBounded B (g x y) (c₂ , c₂')) →
+ (z : val B) →
+ (y : val color) → (n : val nat) → (l : val (list A)) → (t : val (irbt A y n l)) →
+ IsBounded B (mapreduce/seq y n l t f g z) (mapreduce/work c₁ c₂ l , mapreduce/span c₁' c₂' y n)
+ mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z .black .zero .[] leaf =
+ Eq.subst₂
+ (λ c c' → IsBounded B (mapreduce/seq black 0 [] leaf f g z) (c , c'))
+ (Eq.sym (Nat.*-zeroʳ (c₁ + 2 * c₂)))
+ (Eq.sym (Nat.*-zeroʳ (2 * c₁' + 4 * c₂')))
+ ≤⁻-refl
+ mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z .red n l (red {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (
+ bind (F B)
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ _ →
+ bind (F B) (f a) (λ _ →
+ bind (F B) (g _ _) (λ _ →
+ bind (F B) (g _ _) ret)))
+ (λ _ → ret triv)
+ ≡⟨⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (g b s₂) λ s₃ →
+ bind cost (g s₁ s₃) λ _ →
+ ret triv
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoʳ-≤⁻ (f a) (λ b →
+ bind-monoʳ-≤⁻ (g b s₂) (λ s₃ → g-bound))) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (g b s₂) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoʳ-≤⁻ (f a) (λ b →
+ bind-monoˡ-≤⁻ (λ _ → step⋆ (c₂ , c₂')) g-bound)) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoˡ-≤⁻ (λ _ → bind cost (step⋆ (c₂ , c₂')) λ _ → step⋆ (c₂ , c₂')) f-bound) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoˡ-≤⁻ (λ _ → bind cost (step⋆ (c₁ , c₁')) λ _ → bind cost (step⋆ (c₂ , c₂')) λ _ → step⋆ (c₂ , c₂'))
+ (bound/par
+ {e₁ = mapreduce/seq _ _ _ t₁ f g z}
+ {c₁ = mapreduce/work c₁ c₂ l₁ , mapreduce/span c₁' c₂' black n}
+ (mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z black n l₁ t₁)
+ (mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z black n l₂ t₂)) ⟩
+ (
+ bind cost (step⋆ ((mapreduce/work c₁ c₂ l₁ , mapreduce/span c₁' c₂' black n) ⊗ (mapreduce/work c₁ c₂ l₂ , mapreduce/span c₁' c₂' black n))) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≡⟨ Eq.cong
+ (λ c → bind cost (step⋆ c) (λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')))
+ {x = (mapreduce/work c₁ c₂ l₁ , mapreduce/span c₁' c₂' black n) ⊗ (mapreduce/work c₁ c₂ l₂ , mapreduce/span c₁' c₂' black n)}
+ (Eq.cong₂ _,_ refl (Nat.⊔-idem (mapreduce/span c₁' c₂' black n))) ⟩
+ (
+ bind cost (step⋆ (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂) , (2 * c₁' + 4 * c₂') * n)) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≡⟨⟩
+ step⋆ ((((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂)) + (c₁ + (c₂ + c₂)) ,
+ ((2 * c₁' + 4 * c₂') * n) + (c₁' + (c₂' + c₂')))
+ ≡⟨ Eq.cong₂ (λ c c' → step⋆ (c , c')) arithemtic₁ arithemtic₂ ⟩
+ step⋆ (mapreduce/work c₁ c₂ l , mapreduce/span c₁' c₂' red n)
+ ∎
+ where
+ arithemtic₁ : (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂)) + (c₁ + (c₂ + c₂)) ≡ (c₁ + 2 * c₂) * length l
+ arithemtic₁ =
+ let open ≡-Reasoning in
+ begin
+ (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂)) + (c₁ + (c₂ + c₂))
+ ≡˘⟨ Eq.cong₂ _+_
+ (Nat.*-distribˡ-+ (c₁ + 2 * c₂) (length l₁) (length l₂))
+ (Eq.cong₂ _+_ {x = c₁} refl (Eq.trans (Nat.*-distribʳ-+ c₂ 1 1) (Eq.cong₂ _+_ (Nat.*-identityˡ c₂) (Nat.*-identityˡ c₂)))) ⟩
+ ((c₁ + 2 * c₂) * (length l₁ + length l₂)) + (c₁ + 2 * c₂)
+ ≡˘⟨ Eq.cong₂ _+_ refl (Nat.*-identityʳ (c₁ + 2 * c₂)) ⟩
+ ((c₁ + 2 * c₂) * (length l₁ + length l₂)) + (c₁ + 2 * c₂) * 1
+ ≡˘⟨ Nat.*-distribˡ-+ (c₁ + 2 * c₂) (length l₁ + length l₂) 1 ⟩
+ (c₁ + 2 * c₂) * (length l₁ + length l₂ + 1)
+ ≡⟨ Eq.cong₂ _*_ {x = c₁ + 2 * c₂} refl (list/preserves/length' l₁ a l₂) ⟩
+ (c₁ + 2 * c₂) * length l
+ ∎
+
+ arithemtic₂ : (2 * c₁' + 4 * c₂') * n + (c₁' + (c₂' + c₂')) ≡ (2 * c₁' + 4 * c₂') * n + (c₁' + 2 * c₂')
+ arithemtic₂ =
+ let open ≡-Reasoning in
+ begin
+ (2 * c₁' + 4 * c₂') * n + (c₁' + (c₂' + c₂'))
+ ≡˘⟨ Eq.cong₂ _+_
+ {x = (2 * c₁' + 4 * c₂') * n}
+ refl
+ (Eq.cong₂ _+_ {x = c₁'} refl (Eq.trans (Nat.*-distribʳ-+ c₂' 1 1) (Eq.cong₂ _+_ (Nat.*-identityˡ c₂') (Nat.*-identityˡ c₂')))) ⟩
+ (2 * c₁' + 4 * c₂') * n + (c₁' + 2 * c₂')
+ ∎
+ mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z .black n@(suc n') l (black {y₁ = y₁} {y₂ = y₂} {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (
+ bind (F B)
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ _ →
+ bind (F B) (f a) (λ _ →
+ bind (F B) (g _ _) (λ _ →
+ bind (F B) (g _ _) ret)))
+ (λ _ → ret triv)
+ ≡⟨⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (g b s₂) λ s₃ →
+ bind cost (g s₁ s₃) λ _ →
+ ret triv
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoʳ-≤⁻ (f a) (λ b →
+ bind-monoʳ-≤⁻ (g b s₂) (λ s₃ → g-bound))) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (g b s₂) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoʳ-≤⁻ (f a) (λ b →
+ bind-monoˡ-≤⁻ (λ _ → step⋆ (c₂ , c₂')) g-bound)) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (f a) λ b →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoʳ-≤⁻ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) (λ (s₁ , s₂) →
+ bind-monoˡ-≤⁻ (λ _ → bind cost (step⋆ (c₂ , c₂')) λ _ → step⋆ (c₂ , c₂')) f-bound) ⟩
+ (
+ bind cost
+ ((mapreduce/seq _ _ _ t₁ f g z) ∥ (mapreduce/seq _ _ _ t₂ f g z)) λ (s₁ , s₂) →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoˡ-≤⁻ (λ _ → bind cost (step⋆ (c₁ , c₁')) λ _ → bind cost (step⋆ (c₂ , c₂')) λ _ → step⋆ (c₂ , c₂'))
+ (bound/par
+ {e₁ = mapreduce/seq _ _ _ t₁ f g z}
+ {c₁ = mapreduce/work c₁ c₂ l₁ , mapreduce/span c₁' c₂' y₁ n'}
+ (mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z y₁ n' l₁ t₁)
+ (mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z y₂ n' l₂ t₂)) ⟩
+ (
+ bind cost (step⋆ ((mapreduce/work c₁ c₂ l₁ , mapreduce/span c₁' c₂' y₁ n') ⊗ (mapreduce/work c₁ c₂ l₂ , mapreduce/span c₁' c₂' y₂ n'))) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≤⟨ bind-monoˡ-≤⁻
+ (λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂'))
+ (step⋆-mono-≤⁻ {c = mapreduce/work c₁ c₂ l₁ + mapreduce/work c₁ c₂ l₂ , mapreduce/span c₁' c₂' y₁ n' Nat.⊔ mapreduce/span c₁' c₂' y₂ n'}
+ (Nat.≤-refl , Nat.⊔-mono-≤ (span/bounded c₁' c₂' y₁ n') (span/bounded c₁' c₂' y₂ n'))) ⟩
+ (
+ bind cost (step⋆ ((mapreduce/work c₁ c₂ l₁ , mapreduce/span' c₁' c₂' n') ⊗ (mapreduce/work c₁ c₂ l₂ , mapreduce/span' c₁' c₂' n'))) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≡⟨ Eq.cong
+ (λ c → bind cost (step⋆ c) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂'))
+ {x = mapreduce/work c₁ c₂ l₁ + mapreduce/work c₁ c₂ l₂ , mapreduce/span' c₁' c₂' n' Nat.⊔ mapreduce/span' c₁' c₂' n'}
+ (Eq.cong₂ _,_ refl (Nat.⊔-idem ((2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')))) ⟩
+ (
+ bind cost (step⋆ (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂) , (2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂'))) λ _ →
+ bind cost (step⋆ (c₁ , c₁')) λ _ →
+ bind cost (step⋆ (c₂ , c₂')) λ _ →
+ step⋆ (c₂ , c₂')
+ )
+ ≡⟨⟩
+ step⋆ (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂) + (c₁ + (c₂ + c₂)) ,
+ ((2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')) + (c₁' + (c₂' + c₂')) )
+ ≡⟨ Eq.cong₂ (λ c c' → step⋆ (c , c')) arithemtic₁ arithemtic₂ ⟩
+ step⋆ (mapreduce/work c₁ c₂ l , mapreduce/span c₁' c₂' black n)
+ ∎
+ where
+ arithemtic₁ : ((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂) + (c₁ + (c₂ + c₂)) ≡ (c₁ + 2 * c₂) * length l
+ arithemtic₁ =
+ let open ≡-Reasoning in
+ begin
+ (((c₁ + 2 * c₂) * length l₁) + ((c₁ + 2 * c₂) * length l₂)) + (c₁ + (c₂ + c₂))
+ ≡˘⟨ Eq.cong₂ _+_
+ (Nat.*-distribˡ-+ (c₁ + 2 * c₂) (length l₁) (length l₂))
+ (Eq.cong₂ _+_ {x = c₁} refl (Eq.trans (Nat.*-distribʳ-+ c₂ 1 1) (Eq.cong₂ _+_ (Nat.*-identityˡ c₂) (Nat.*-identityˡ c₂)))) ⟩
+ ((c₁ + 2 * c₂) * (length l₁ + length l₂)) + (c₁ + 2 * c₂)
+ ≡˘⟨ Eq.cong₂ _+_ refl (Nat.*-identityʳ (c₁ + 2 * c₂)) ⟩
+ ((c₁ + 2 * c₂) * (length l₁ + length l₂)) + (c₁ + 2 * c₂) * 1
+ ≡˘⟨ Nat.*-distribˡ-+ (c₁ + 2 * c₂) (length l₁ + length l₂) 1 ⟩
+ (c₁ + 2 * c₂) * (length l₁ + length l₂ + 1)
+ ≡⟨ Eq.cong₂ _*_ {x = c₁ + 2 * c₂} refl (list/preserves/length' l₁ a l₂) ⟩
+ (c₁ + 2 * c₂) * length l
+ ∎
+
+ arithemtic₂ : ((2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')) + (c₁' + (c₂' + c₂')) ≡ (2 * c₁' + 4 * c₂') * n
+ arithemtic₂ =
+ let open ≡-Reasoning in
+ begin
+ ((2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')) + (c₁' + (c₂' + c₂'))
+ ≡˘⟨ Eq.cong₂ _+_
+ {x = (2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')}
+ refl
+ (Eq.cong₂ _+_ {x = c₁'} refl (Eq.trans (Nat.*-distribʳ-+ c₂' 1 1) (Eq.cong₂ _+_ (Nat.*-identityˡ c₂') (Nat.*-identityˡ c₂')))) ⟩
+ ((2 * c₁' + 4 * c₂') * n' + (c₁' + 2 * c₂')) + (c₁' + 2 * c₂')
+ ≡⟨ Nat.+-assoc ((2 * c₁' + 4 * c₂') * n') (c₁' + 2 * c₂') (c₁' + 2 * c₂') ⟩
+ (2 * c₁' + 4 * c₂') * n' + ((c₁' + 2 * c₂') + (c₁' + 2 * c₂'))
+ ≡˘⟨ Eq.cong₂ _+_
+ {x = (2 * c₁' + 4 * c₂') * n'}
+ refl
+ (Eq.trans (Nat.*-distribʳ-+ (c₁' + 2 * c₂') 1 1) (Eq.cong₂ _+_ (Nat.*-identityˡ (c₁' + 2 * c₂')) (Nat.*-identityˡ (c₁' + 2 * c₂')))) ⟩
+ (2 * c₁' + 4 * c₂') * n' + 2 * (c₁' + 2 * c₂')
+ ≡⟨ Eq.cong₂ _+_
+ {x = (2 * c₁' + 4 * c₂') * n'}
+ refl
+ (Nat.*-distribˡ-+ 2 c₁' (2 * c₂')) ⟩
+ (2 * c₁' + 4 * c₂') * n' + (2 * c₁' + 2 * (2 * c₂'))
+ ≡⟨ Eq.cong (λ x → (2 * c₁' + 4 * c₂') * n' + (2 * c₁' + x)) (Eq.sym (Nat.*-assoc 2 2 c₂')) ⟩
+ (2 * c₁' + 4 * c₂') * n' + (2 * c₁' + 4 * c₂')
+ ≡⟨ Nat.+-comm ((2 * c₁' + 4 * c₂') * n') (2 * c₁' + 4 * c₂') ⟩
+ (2 * c₁' + 4 * c₂') + (2 * c₁' + 4 * c₂') * n'
+ ≡˘⟨ Nat.*-suc (2 * c₁' + 4 * c₂') n' ⟩
+ (2 * c₁' + 4 * c₂') * n
+ ∎
+
+ mapreduce/is-bounded :
+ {c₁ c₁' c₂ c₂' : val nat} →
+ (f : cmp (Π A λ _ → F B)) →
+ ({x : val A} → IsBounded B (f x) (c₁ , c₁')) →
+ (g : cmp (Π B λ _ → Π B λ _ → F B)) →
+ ({x y : val B} → IsBounded B (g x y) (c₂ , c₂')) →
+ (z : val B) →
+ (y : val color) → (n : val nat) → (l : val (list A)) → (t : val (irbt A y n l)) →
+ IsBounded B (mapreduce/seq y n l t f g z) ((c₁ + 2 * c₂) * length l , (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + length l) ⌉ + (c₁' + 2 * c₂'))
+ mapreduce/is-bounded {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z y n l t =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (mapreduce/seq y n l t f g z) (λ _ → ret triv)
+ ≤⟨ mapreduce/is-bounded' {c₁} {c₁'} {c₂} {c₂'} f f-bound g g-bound z y n l t ⟩
+ step⋆ (mapreduce/work c₁ c₂ l , mapreduce/span c₁' c₂' y n)
+ ≤⟨ step⋆-mono-≤⁻ (Nat.≤-refl {mapreduce/work c₁ c₂ l}, span/bounded c₁' c₂' y n) ⟩
+ step⋆ (mapreduce/work c₁ c₂ l , mapreduce/span' c₁' c₂' n)
+ ≤⟨ step⋆-mono-≤⁻ (Nat.≤-refl {mapreduce/work c₁ c₂ l} , lemma) ⟩
+ step⋆ ((c₁ + 2 * c₂) * length l , (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + length l) ⌉ + (c₁' + 2 * c₂'))
+ ∎
+ where
+ lemma : mapreduce/span' c₁' c₂' n Nat.≤ (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + length l) ⌉ + (c₁' + 2 * c₂')
+ lemma =
+ let open Nat.≤-Reasoning in
+ begin
+ (2 * c₁' + 4 * c₂') * n + (c₁' + 2 * c₂')
+ ≤⟨ Nat.+-monoˡ-≤ (c₁' + 2 * c₂') (Nat.*-monoʳ-≤ (2 * c₁' + 4 * c₂') (i-nodes/bound/log-node-black-height t)) ⟩
+ (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + i-nodes t) ⌉ + (c₁' + 2 * c₂')
+ ≡⟨ Eq.cong (λ x → (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + x) ⌉ + (c₁' + 2 * c₂')) (i-nodes≡lengthl t) ⟩
+ (2 * c₁' + 4 * c₂') * ⌈log₂ (1 + length l) ⌉ + (c₁' + 2 * c₂')
+ ∎
+
+
+module Sum where
+ sum/seq : cmp $
+ Π color λ y → Π nat λ n → Π (list nat) λ l → Π (irbt nat y n l) λ _ → F nat
+ sum/seq .black .zero .[] leaf = ret 0
+ sum/seq .red n l (red t₁ a t₂) =
+ step (F nat) (1 , 1) $
+ bind (F (nat)) ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ (s₁ , s₂) → ret (s₁ + a + s₂))
+ sum/seq .black n l (black t₁ a t₂) =
+ step (F nat) (1 , 1) $
+ bind (F (nat)) ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ (s₁ , s₂) → ret (s₁ + a + s₂))
+
+ span/sum : val color → val nat → val nat
+ span/sum red n = 1 + 2 * n
+ span/sum black n = 2 * n
+
+ span/bounded : ∀ y n → (span/sum y n) Nat.≤ (1 + 2 * n)
+ span/bounded red n = Nat.≤-refl
+ span/bounded black n = Nat.n≤1+n (2 * n)
+
+ sum/bounded' : ∀ y n l t → IsBounded nat (sum/seq y n l t) (length l , span/sum y n)
+ sum/bounded' .black .zero .[] leaf = ≤⁻-refl
+ sum/bounded' .red n l (red {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ let open ≤⁻-Reasoning cost in
+ begin
+ step cost (1 , 1) (
+ bind cost (
+ bind (F (nat)) ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ (s₁ , s₂) → ret (s₁ + a + s₂)))
+ (λ _ → ret triv))
+ ≡⟨⟩
+ step cost (1 , 1) (
+ bind cost ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ _ → ret triv))
+ ≤⟨
+ ≤⁻-mono
+ (step cost (1 , 1))
+ (bound/par
+ {e₁ = sum/seq _ _ _ t₁}
+ {c₁ = (length l₁ , span/sum black n)}
+ (sum/bounded' black n l₁ t₁)
+ (sum/bounded' black n l₂ t₂))
+ ⟩
+ step cost (1 , 1) (
+ step⋆ ((length l₁ , span/sum black n) ⊗ (length l₂ , span/sum black n)))
+ ≡⟨ Eq.cong (λ c → step cost (1 , 1) (step⋆ c)) (Eq.cong₂ _,_ refl (Nat.⊔-idem (span/sum black n))) ⟩
+ step cost (1 , 1) (
+ step⋆ (length l₁ + length l₂ , span/sum black n))
+ ≡⟨⟩
+ step⋆ (1 + (length l₁ + length l₂) , 1 + 2 * n)
+ ≡⟨ Eq.cong₂ (λ c₁ c₂ → step⋆ (c₁ , c₂)) (list/preserves/length l₁ a l₂) refl ⟩
+ step⋆ (length l , span/sum red n)
+ ∎
+ sum/bounded' .black n@(suc n') l (black {y₁ = y₁} {y₂ = y₂} {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ let open ≤⁻-Reasoning cost in
+ begin
+ step cost (1 , 1) (
+ bind cost (
+ bind (F (nat)) ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ (s₁ , s₂) → ret (s₁ + a + s₂)))
+ (λ _ → ret triv))
+ ≡⟨⟩
+ step cost (1 , 1) (
+ bind cost ((sum/seq _ _ _ t₁) ∥ (sum/seq _ _ _ t₂))
+ (λ _ → ret triv))
+ ≤⟨ ≤⁻-mono
+ (step cost (1 , 1))
+ (bound/par
+ {e₁ = sum/seq _ _ _ t₁}
+ {c₁ = (length l₁ , span/sum y₁ n')}
+ (sum/bounded' y₁ n' l₁ t₁)
+ (sum/bounded' y₂ n' l₂ t₂)) ⟩
+ step cost (1 , 1) (
+ step⋆ ((length l₁ , span/sum y₁ n') ⊗ (length l₂ , span/sum y₂ n')))
+ ≤⟨ ≤⁻-mono
+ (λ e → step cost (1 , 1) e)
+ (step⋆-mono-≤⁻
+ (Nat.≤-refl , Nat.⊔-mono-≤ (span/bounded y₁ n') (span/bounded y₂ n'))) ⟩
+ step cost (1 , 1) (
+ step⋆ ((length l₁ , 1 + 2 * n') ⊗ (length l₂ , 1 + 2 * n')))
+ ≡⟨ Eq.cong (λ c → step cost (1 , 1) (step⋆ c)) (Eq.cong₂ _,_ refl (Nat.⊔-idem (1 + 2 * n'))) ⟩
+ step cost (1 , 1) (
+ step⋆ (length l₁ + length l₂ , 1 + 2 * n'))
+ ≡⟨⟩
+ step⋆ (1 + (length l₁ + length l₂) , 1 + (1 + 2 * n'))
+ ≡⟨ Eq.cong₂ (λ c₁ c₂ → step⋆ (c₁ , c₂)) (list/preserves/length l₁ a l₂) (arithemtic n') ⟩
+ step⋆ (length l , span/sum black n)
+ ∎
+ where
+ arithemtic : ∀ n → 1 + (1 + 2 * n) ≡ 2 * (suc n)
+ arithemtic n =
+ let open ≡-Reasoning in
+ begin
+ 1 + (1 + 2 * n)
+ ≡⟨ Nat.+-assoc 1 1 (2 * n) ⟩
+ (1 + 1) + 2 * n
+ ≡⟨⟩
+ 2 + 2 * n
+ ≡˘⟨ Nat.*-suc 2 n ⟩
+ 2 * (suc n)
+ ∎
+
+ sum/bounded : ∀ y n l t → IsBounded nat (sum/seq y n l t) (length l , 1 + 2 * ⌈log₂ (1 + length l) ⌉)
+ sum/bounded y n l t =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (sum/seq y n l t) (λ _ → ret triv)
+ ≤⟨ sum/bounded' y n l t ⟩
+ step⋆ (length l , span/sum y n)
+ ≤⟨ step⋆-mono-≤⁻ (Nat.≤-refl {length l} , lemma) ⟩
+ step⋆ (length l , 1 + 2 * ⌈log₂ (1 + length l) ⌉)
+ ∎
+ where
+ lemma : span/sum y n Nat.≤ 1 + (2 * ⌈log₂ (1 + length l) ⌉)
+ lemma =
+ let open Nat.≤-Reasoning in
+ begin
+ span/sum y n
+ ≤⟨ span/bounded y n ⟩
+ 1 + (2 * n)
+ ≤⟨ Nat.s≤s (Nat.*-monoʳ-≤ 2 (i-nodes/bound/log-node-black-height t)) ⟩
+ 1 + (2 * ⌈log₂ (1 + i-nodes t) ⌉)
+ ≡⟨ Eq.cong (λ x → 1 + (2 * ⌈log₂ (1 + x) ⌉)) (i-nodes≡lengthl t) ⟩
+ 1 + (2 * ⌈log₂ (1 + length l) ⌉)
+ ∎
diff --git a/src/Examples/Sequence/ListMSequence.agda b/src/Examples/Sequence/ListMSequence.agda
new file mode 100644
index 00000000..768f7f6a
--- /dev/null
+++ b/src/Examples/Sequence/ListMSequence.agda
@@ -0,0 +1,35 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence.ListMSequence where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+open import Calf.Data.List
+open import Data.Nat as Nat using (_+_)
+
+open import Examples.Sequence.MSequence
+
+ListMSequence : MSequence
+ListMSequence =
+ record
+ { seq = list
+ ; empty = ret []
+ ; join =
+ λ {A} l₁ a l₂ →
+ let n = length l₁ + 1 + length l₂ in
+ step (F (list A)) (n , n) (ret (l₁ ++ [ a ] ++ l₂))
+ ; rec = λ {A} {X} → rec {A} {X}
+ }
+ where
+ rec : {X : tp⁻} →
+ cmp
+ ( Π (U X) λ _ →
+ Π (U (Π (list A) λ _ → Π (U X) λ _ → Π A λ _ → Π (list A) λ _ → Π (U X) λ _ → X)) λ _ →
+ Π (list A) λ _ → X
+ )
+ rec {A} {X} z f [] = z
+ rec {A} {X} z f (x ∷ l) = step X (1 , 1) (f [] z x l (rec {A} {X} z f l))
diff --git a/src/Examples/Sequence/MSequence.agda b/src/Examples/Sequence/MSequence.agda
new file mode 100644
index 00000000..bed07a64
--- /dev/null
+++ b/src/Examples/Sequence/MSequence.agda
@@ -0,0 +1,25 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence.MSequence where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+
+-- Middle Sequence
+record MSequence : Set where
+ field
+ seq : tp⁺ → tp⁺
+
+ empty : cmp (F (seq A))
+ join : cmp (Π (seq A) λ s₁ → Π A λ a → Π (seq A) λ s₂ → F (seq A))
+
+ rec : {X : tp⁻} →
+ cmp
+ ( Π (U X) λ _ →
+ Π (U (Π (seq A) λ _ → Π (U X) λ _ → Π A λ _ → Π (seq A) λ _ → Π (U X) λ _ → X)) λ _ →
+ Π (seq A) λ _ → X
+ )
diff --git a/src/Examples/Sequence/RedBlackMSequence.agda b/src/Examples/Sequence/RedBlackMSequence.agda
new file mode 100644
index 00000000..3357fa8e
--- /dev/null
+++ b/src/Examples/Sequence/RedBlackMSequence.agda
@@ -0,0 +1,122 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence.RedBlackMSequence where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+
+open import Calf.Data.Nat
+open import Calf.Data.List
+open import Calf.Data.Product
+open import Calf.Data.Sum
+open import Calf.Data.IsBounded costMonoid
+open import Calf.Data.IsBoundedG costMonoid
+
+open import Data.Nat as Nat using (_+_; _*_; ⌊_/2⌋; _≥_; _∸_)
+import Data.Nat.Properties as Nat
+open import Data.Nat.Logarithm
+
+open import Relation.Binary
+open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl)
+
+open import Examples.Sequence.MSequence
+open import Examples.Sequence.RedBlackTree
+
+
+RedBlackMSequence : MSequence
+RedBlackMSequence =
+ record
+ { seq = rbt
+ ; empty = ret ⟪ leaf ⟫
+ ; join = join
+ ; rec = λ {A} {X} → rec {A} {X}
+ }
+ where
+ record RBT (A : tp⁺) : Set where
+ pattern
+ constructor ⟪_⟫
+ field
+ {y} : val color
+ {n} : val nat
+ {l} : val (list A)
+ t : val (irbt A y n l)
+ rbt : (A : tp⁺) → tp⁺
+ rbt A = meta⁺ (RBT A)
+
+ joinCont : ∀ (t₁ : RBT A) (t₂ : RBT A) a → Σ Color (λ c → Σ (List (val A)) (λ l → Σ (l ≡ (RBT.l t₁ ++ [ a ] ++ RBT.l t₂)) (λ x →
+ IRBT A c (suc (RBT.n t₁ ⊔ RBT.n t₂)) l ⊎ IRBT A c (RBT.n t₁ ⊔ RBT.n t₂) l))) → cmp (F (rbt A))
+ joinCont _ _ _ (_ , _ , _ , inj₁ t) = ret ⟪ t ⟫
+ joinCont _ _ _ (_ , _ , _ , inj₂ t) = ret ⟪ t ⟫
+
+ join : cmp (Π (rbt A) λ _ → Π A λ _ → Π (rbt A) λ _ → F (rbt A))
+ join {A} t₁ a t₂ = bind (F (rbt A)) (i-join _ _ _ (RBT.t t₁) a _ _ _ (RBT.t t₂)) (joinCont t₁ t₂ a)
+
+ join/is-bounded : ∀ {A} t₁ a t₂ → IsBounded (rbt A) (join t₁ a t₂)
+ (1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)) , 1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)))
+ join/is-bounded {A} t₁ a t₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (
+ bind (F (rbt A)) (i-join _ _ _ (RBT.t t₁) a _ _ _ (RBT.t t₂)) (joinCont t₁ t₂ a))
+ (λ _ → ret triv)
+ ≡⟨ Eq.cong
+ (λ f → bind cost (i-join _ _ _ (RBT.t t₁) a _ _ _ (RBT.t t₂)) f)
+ (funext (λ { (_ , _ , _ , inj₁ _) → refl
+ ; (_ , _ , _ , inj₂ _) → refl })) ⟩
+ bind cost (i-join _ _ _ (RBT.t t₁) a _ _ _ (RBT.t t₂)) (λ _ → ret triv)
+ ≤⟨ i-join/is-bounded _ _ _ (RBT.t t₁) a _ _ _ (RBT.t t₂) ⟩
+ step⋆ (1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)) , 1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)))
+ ∎
+
+ nodes : RBT A → val nat
+ nodes ⟪ t ⟫ = i-nodes t
+
+ nodes/upper-bound : (t : RBT A) → RBT.n t Nat.≤ ⌈log₂ (1 + (nodes t)) ⌉
+ nodes/upper-bound ⟪ t ⟫ = i-nodes/bound/log-node-black-height t
+
+ nodes/lower-bound : (t : RBT A) → RBT.n t Nat.≥ ⌊ (⌈log₂ (1 + (nodes t)) ⌉ ∸ 1) /2⌋
+ nodes/lower-bound ⟪ t ⟫ = i-nodes/lower-bound/log-node-black-height t
+
+ join/cost : ∀ {A} (t₁ : RBT A) (t₂ : RBT A) → ℂ
+ join/cost {A} t₁ t₂ =
+ let max = ⌈log₂ (1 + (nodes t₁)) ⌉ Nat.⊔ ⌈log₂ (1 + (nodes t₂)) ⌉ in
+ let min = ⌊ (⌈log₂ (1 + (nodes t₁)) ⌉ ∸ 1) /2⌋ Nat.⊓ ⌊ (⌈log₂ (1 + (nodes t₂)) ⌉ ∸ 1) /2⌋ in
+ (1 + 2 * (max ∸ min)) , (1 + 2 * (max ∸ min))
+
+ join/is-bounded/nodes : ∀ {A} t₁ a t₂ → IsBounded (rbt A) (join t₁ a t₂) (join/cost t₁ t₂)
+ join/is-bounded/nodes {A} t₁ a t₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (join t₁ a t₂) (λ _ → ret triv)
+ ≤⟨ join/is-bounded t₁ a t₂ ⟩
+ step⋆ (1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)) , 1 + (2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)))
+ ≤⟨ step⋆-mono-≤⁻ (black-height-cost/to/node-cost , black-height-cost/to/node-cost) ⟩
+ step⋆ (join/cost t₁ t₂)
+ ∎
+ where
+ black-height-cost/to/node-cost : 1 + 2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂) Nat.≤ 1 + 2 * (⌈log₂ (1 + (nodes t₁)) ⌉ Nat.⊔ ⌈log₂ (1 + (nodes t₂)) ⌉ ∸ ⌊ (⌈log₂ (1 + (nodes t₁)) ⌉ ∸ 1) /2⌋ Nat.⊓ ⌊ (⌈log₂ (1 + (nodes t₂)) ⌉ ∸ 1) /2⌋)
+ black-height-cost/to/node-cost =
+ let open Nat.≤-Reasoning in
+ begin
+ 1 + 2 * (RBT.n t₁ Nat.⊔ RBT.n t₂ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)
+ ≤⟨ Nat.+-monoʳ-≤ 1 (Nat.*-monoʳ-≤ 2 (Nat.∸-monoˡ-≤ (RBT.n t₁ Nat.⊓ RBT.n t₂) (Nat.⊔-mono-≤ (nodes/upper-bound t₁) (nodes/upper-bound t₂)))) ⟩
+ 1 + 2 * (⌈log₂ (1 + (nodes t₁)) ⌉ Nat.⊔ ⌈log₂ (1 + (nodes t₂)) ⌉ ∸ RBT.n t₁ Nat.⊓ RBT.n t₂)
+ ≤⟨ Nat.+-monoʳ-≤ 1 (Nat.*-monoʳ-≤ 2 (Nat.∸-monoʳ-≤ (⌈log₂ (1 + (nodes t₁)) ⌉ Nat.⊔ ⌈log₂ (1 + (nodes t₂)) ⌉) (Nat.⊓-mono-≤ (nodes/lower-bound t₁) (nodes/lower-bound t₂)))) ⟩
+ 1 + 2 * (⌈log₂ (1 + (nodes t₁)) ⌉ Nat.⊔ ⌈log₂ (1 + (nodes t₂)) ⌉ ∸ ⌊ (⌈log₂ (1 + (nodes t₁)) ⌉ ∸ 1) /2⌋ Nat.⊓ ⌊ (⌈log₂ (1 + (nodes t₂)) ⌉ ∸ 1) /2⌋)
+ ∎
+
+ rec : {A : tp⁺} {X : tp⁻} →
+ cmp
+ ( Π (U X) λ _ →
+ Π (U (Π (rbt A) λ _ → Π (U X) λ _ → Π A λ _ → Π (rbt A) λ _ → Π (U X) λ _ → X)) λ _ →
+ Π (rbt A) λ _ → X
+ )
+ rec {A} {X} z f ⟪ t ⟫ =
+ i-rec {A} {X}
+ z
+ (λ _ _ _ t₁ ih₁ a _ _ _ t₂ ih₂ → f ⟪ t₁ ⟫ ih₁ a ⟪ t₂ ⟫ ih₂)
+ _ _ _ t
diff --git a/src/Examples/Sequence/RedBlackTree.agda b/src/Examples/Sequence/RedBlackTree.agda
new file mode 100644
index 00000000..625c915b
--- /dev/null
+++ b/src/Examples/Sequence/RedBlackTree.agda
@@ -0,0 +1,701 @@
+{-# OPTIONS --prop --rewriting #-}
+
+module Examples.Sequence.RedBlackTree where
+
+open import Algebra.Cost
+
+parCostMonoid = ℕ²-ParCostMonoid
+open ParCostMonoid parCostMonoid
+
+open import Calf costMonoid
+
+open import Calf.Data.Product
+open import Calf.Data.Sum
+open import Calf.Data.Nat
+open import Calf.Data.List
+open import Calf.Data.IsBounded costMonoid
+open import Calf.Data.IsBoundedG costMonoid
+open import Data.Nat as Nat using (_+_; _*_; _∸_)
+open import Data.Nat.Logarithm
+import Data.Nat.Properties as Nat
+import Data.List.Properties as List
+
+open import Function using (_$_)
+
+open import Relation.Nullary
+open import Relation.Binary
+open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl; _≢_; module ≡-Reasoning; ≢-sym)
+
+
+data Color : Set where
+ red : Color
+ black : Color
+color : tp⁺
+color = meta⁺ Color
+
+-- Indexed Red Black Tree
+data IRBT (A : tp⁺) : val color → val nat → val (list A) → Set where
+ leaf : IRBT A black zero []
+ red : {n : val nat} {l₁ l₂ : val (list A)}
+ (t₁ : IRBT A black n l₁) (a : val A) (t₂ : IRBT A black n l₂)
+ → IRBT A red n (l₁ ++ [ a ] ++ l₂)
+ black : {n : val nat} {y₁ y₂ : val color} {l₁ l₂ : val (list A)}
+ (t₁ : IRBT A y₁ n l₁) (a : val A) (t₂ : IRBT A y₂ n l₂)
+ → IRBT A black (suc n) (l₁ ++ [ a ] ++ l₂)
+irbt : (A : tp⁺) → val color → val nat → val (list A) → tp⁺
+irbt A y n l = meta⁺ (IRBT A y n l)
+
+
+data AlmostLeftRBT (A : tp⁺) : (right-color : val color) → val nat → val (list A) → Set where
+ violation :
+ {n : val nat} {l₁ l₂ : val (list A)}
+ → IRBT A red n l₁ → (a : val A) → IRBT A black n l₂
+ → AlmostLeftRBT A red n (l₁ ++ [ a ] ++ l₂)
+ valid :
+ {right-color : val color} {n : val nat} {y : val color} {l : val (list A)} → IRBT A y n l
+ → AlmostLeftRBT A right-color n l
+alrbt : (A : tp⁺) → val color → val nat → val (list A) → tp⁺
+alrbt A y n l = meta⁺ (AlmostLeftRBT A y n l)
+
+joinLeftContCase₁ : ∀ l₁ l₂₁ l₂₂ a a₁ n₂ t₂₂ →
+ (Σ (List (val A)) λ l → Σ ((l ≡ l₁ ++ [ a ] ++ l₂₁)) (λ _ → (AlmostLeftRBT A black n₂ l))) →
+ cmp (F (Σ⁺ (list A) λ l → (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂₁ ++ [ a₁ ] ++ l₂₂)) ×⁺ (alrbt A red n₂ l)))
+joinLeftContCase₁ {A} l₁ l₂₁ l₂₂ a a₁ n₂ t₂₂ (l , l≡l₂₁++a₁∷l₂₂ , valid {y = red} t') =
+ ret (((l₁ ++ [ a ] ++ l₂₁) ++ [ a₁ ] ++ l₂₂) ,
+ (List.++-assoc l₁ (a ∷ l₂₁) (a₁ ∷ l₂₂) ,
+ (Eq.subst (λ l' → AlmostLeftRBT A red n₂ l') (Eq.cong₂ _++_ l≡l₂₁++a₁∷l₂₂ refl) (violation t' a₁ t₂₂))))
+joinLeftContCase₁ {A} l₁ l₂₁ l₂₂ a a₁ n₂ t₂₂ (l , l≡l₂₁++a₁∷l₂₂ , valid {y = black} t') =
+ ret (((l₁ ++ [ a ] ++ l₂₁) ++ [ a₁ ] ++ l₂₂) ,
+ (List.++-assoc l₁ (a ∷ l₂₁) (a₁ ∷ l₂₂) ,
+ Eq.subst (λ l' → AlmostLeftRBT A red n₂ l') (Eq.cong₂ _++_ l≡l₂₁++a₁∷l₂₂ refl) (valid (red t' a₁ t₂₂))))
+
+joinLeftContCase₂ : ∀ l₁ l₂₁ l₂₂ a a₁ y₂₁ y₂₂ n₂ (t₂₂ : IRBT A y₂₂ n₂ l₂₂) →
+ (Σ (List (val A))(λ a₂ → Σ (a₂ ≡ l₁ ++ a ∷ l₂₁) (λ x → AlmostLeftRBT A y₂₁ n₂ a₂))) →
+ cmp (F (Σ⁺ (list A) (λ l → meta⁺ (l ≡ l₁ ++ a ∷ l₂₁ ++ a₁ ∷ l₂₂) ×⁺ alrbt A black (suc n₂) l)))
+joinLeftContCase₂ {A} l₁ l₂₁ l₂₂ a a₁ y₂₁ y₂₂ n₂ t₂₂ (l , l≡l₁++a∷l₂₁ , violation {l₂ = l'₂} (red {l₁ = l'₁₁} {l₂ = l'₁₂} t'₁₁ a'₁ t'₁₂) a' t'₂) =
+ ret ((l'₁₁ ++ [ a'₁ ] ++ l'₁₂) ++ [ a' ] ++ (l'₂ ++ [ a₁ ] ++ l₂₂) ,
+ ((begin
+ (l'₁₁ ++ a'₁ ∷ l'₁₂) ++ a' ∷ l'₂ ++ a₁ ∷ l₂₂
+ ≡˘⟨ List.++-assoc (l'₁₁ ++ a'₁ ∷ l'₁₂) (a' ∷ l'₂) (a₁ ∷ l₂₂) ⟩
+ ((l'₁₁ ++ a'₁ ∷ l'₁₂) ++ a' ∷ l'₂) ++ a₁ ∷ l₂₂
+ ≡⟨ Eq.cong₂ _++_ l≡l₁++a∷l₂₁ refl ⟩
+ (l₁ ++ a ∷ l₂₁) ++ a₁ ∷ l₂₂
+ ≡⟨ List.++-assoc l₁ (a ∷ l₂₁) (a₁ ∷ l₂₂) ⟩
+ l₁ ++ a ∷ l₂₁ ++ a₁ ∷ l₂₂
+ ∎) ,
+ (valid (red (black t'₁₁ a'₁ t'₁₂) a' (black t'₂ a₁ t₂₂)))))
+ where open ≡-Reasoning
+joinLeftContCase₂ {A} l₁ l₂₁ l₂₂ a a₁ y₂₁ y₂₂ n₂ t₂₂ (l , l≡l₁++a∷l₂₁ , valid t') =
+ ret (((l₁ ++ [ a ] ++ l₂₁) ++ [ a₁ ] ++ l₂₂) ,
+ (List.++-assoc l₁ (a ∷ l₂₁) (a₁ ∷ l₂₂) ,
+ Eq.subst (λ l' → AlmostLeftRBT A black (suc n₂) l') (Eq.cong₂ _++_ l≡l₁++a∷l₂₁ refl) (valid (black t' a₁ t₂₂))))
+
+joinLeft :
+ cmp
+ ( Π color λ y₁ → Π nat λ n₁ → Π (list A) λ l₁ → Π (irbt A y₁ n₁ l₁) λ _ →
+ Π A λ a →
+ Π color λ y₂ → Π nat λ n₂ → Π (list A) λ l₂ → Π (irbt A y₂ n₂ l₂) λ _ →
+ Π (meta⁺ (n₁ < n₂)) λ _ →
+ F (Σ⁺ (list A) λ l → (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ (alrbt A y₂ n₂ l))
+ )
+joinLeft {A} y₁ n₁ l₁ t₁ a .red n₂ l₂ (red {l₁ = l₂₁} {l₂ = l₂₂} t₂₁ a₁ t₂₂) n₁ n₂)) λ _ →
+ F (Σ⁺ (list A) λ l → (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ (arrbt A y₁ n₁ l))
+ )
+joinRight {A} .red n₁ l₁ (red {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a y₂ n₂ l₂ t₂ n₁>n₂ =
+ step (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A red n₁ l)))) (1 , 1) $
+ bind (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A red n₁ l))))
+ (joinRight _ _ _ t₁₂ a _ _ _ t₂ n₁>n₂)
+ (joinRightContCase₁ l₁₁ l₁₂ l₂ a a₁ n₁ t₁₁)
+joinRight {A} .black (suc n₁) l₁ (black {y₁ = y₁₁} {y₂ = y₁₂} {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a y₂ n₂ l₂ t₂ n₁>n₂ with n₁ Nat.≟ n₂
+joinRight {A} .black (suc n₁) l₁ (black {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a red n₁ l₂ (red {l₁ = l₂₁} {l₂ = l₂₂} t₂₁ a₂ t₂₂) n₁>n₂ | yes refl =
+ ret ((l₁₁ ++ [ a₁ ] ++ l₁₂) ++ [ a ] ++ (l₂₁ ++ [ a₂ ] ++ l₂₂) ,
+ refl ,
+ valid (red (black t₁₁ a₁ t₁₂) a (black t₂₁ a₂ t₂₂)))
+joinRight {A} .black (suc n₁) l₁ (black {y₂ = red} {l₁ = l₁₁} t₁₁ a₁ (red {l₁ = l₁₂₁} {l₂ = l₁₂₂} t₁₂₁ a₁₂ t₁₂₂)) a black n₁ l₂ t₂ n₁>n₂ | yes refl =
+ ret ((l₁₁ ++ [ a₁ ] ++ l₁₂₁) ++ [ a₁₂ ] ++ (l₁₂₂ ++ [ a ] ++ l₂) ,
+ (begin
+ (l₁₁ ++ a₁ ∷ l₁₂₁) ++ a₁₂ ∷ l₁₂₂ ++ a ∷ l₂
+ ≡⟨ List.++-assoc l₁₁ (a₁ ∷ l₁₂₁) (a₁₂ ∷ l₁₂₂ ++ a ∷ l₂) ⟩
+ l₁₁ ++ a₁ ∷ l₁₂₁ ++ a₁₂ ∷ l₁₂₂ ++ a ∷ l₂
+ ≡⟨ Eq.cong₂ _++_ refl (Eq.sym (List.++-assoc (a₁ ∷ l₁₂₁) (a₁₂ ∷ l₁₂₂) (a ∷ l₂))) ⟩
+ l₁₁ ++ (a₁ ∷ l₁₂₁ ++ a₁₂ ∷ l₁₂₂) ++ a ∷ l₂
+ ≡˘⟨ List.++-assoc l₁₁ (a₁ ∷ l₁₂₁ ++ a₁₂ ∷ l₁₂₂) (a ∷ l₂) ⟩
+ (l₁₁ ++ a₁ ∷ l₁₂₁ ++ a₁₂ ∷ l₁₂₂) ++ a ∷ l₂
+ ∎) ,
+ valid (red (black t₁₁ a₁ t₁₂₁) a₁₂ (black t₁₂₂ a t₂)))
+ where open ≡-Reasoning
+joinRight {A} .black (suc n₁) l₁ (black {y₂ = black} {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a black n₁ l₂ t₂ n₁>n₂ | yes refl =
+ ret (l₁₁ ++ [ a₁ ] ++ (l₁₂ ++ [ a ] ++ l₂) ,
+ Eq.sym (List.++-assoc l₁₁ (a₁ ∷ l₁₂) (a ∷ l₂)) ,
+ valid (black t₁₁ a₁ (red t₁₂ a t₂)))
+... | no n₁≢n₂ =
+ step (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A black (suc n₁) l)))) (1 , 1) $
+ bind (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A black (suc n₁) l))))
+ (joinRight _ _ _ t₁₂ a _ _ _ t₂ (Nat.≤∧≢⇒< (Nat.≤-pred n₁>n₂) (≢-sym n₁≢n₂)))
+ (joinRightContCase₂ l₁₁ l₁₂ l₂ a a₁ y₁₁ y₁₂ n₁ t₁₁)
+
+joinRight/cost : (y : val color) (n₁ n₂ : val nat) → ℂ
+joinRight/cost red n₁ n₂ = 1 + (2 * (n₁ ∸ n₂)) , 1 + (2 * (n₁ ∸ n₂))
+joinRight/cost black n₁ n₂ = (2 * (n₁ ∸ n₂)) , (2 * (n₁ ∸ n₂))
+
+joinRight/is-bounded' : ∀ y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂
+ → IsBounded (Σ⁺ (list A) λ l → (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ (arrbt A y₁ n₁ l)) (joinRight y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂) (joinRight/cost y₁ n₁ n₂)
+
+joinRight/is-bounded : ∀ {A} y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂
+ → IsBounded (Σ⁺ (list A) λ l → (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ (arrbt A y₁ n₁ l)) (joinRight y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂) (1 + (2 * (n₁ ∸ n₂)) , 1 + (2 * (n₁ ∸ n₂)))
+
+joinRight/is-bounded' {A} red n₁ l₁ (red {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a y₂ n₂ l₂ t₂ n₁>n₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ step cost (1 , 1) (
+ bind cost (
+ bind (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A red n₁ l))))
+ (joinRight _ _ _ t₁₂ a _ _ _ t₂ n₁>n₂)
+ (joinRightContCase₁ l₁₁ l₁₂ l₂ a a₁ n₁ t₁₁))
+ (λ _ → ret triv))
+ ≡⟨ Eq.cong
+ (λ e → step cost (1 , 1) e)
+ (Eq.cong
+ (λ f → bind cost (joinRight _ _ _ t₁₂ a _ _ _ t₂ n₁>n₂) f)
+ (funext ((λ { (_ , _ , valid {y = red} _) → refl
+ ; (_ , _ , valid {y = black} _) → refl })))) ⟩
+ step cost (1 , 1) (
+ bind cost (joinRight _ _ _ t₁₂ a _ _ _ t₂ n₁>n₂)
+ (λ _ → ret triv))
+ ≤⟨ ≤⁻-mono (λ e → step cost (1 , 1) e) (joinRight/is-bounded' _ _ _ t₁₂ a _ _ _ t₂ n₁>n₂) ⟩
+ step cost (1 , 1) (
+ bind cost (step⋆ (2 * (n₁ ∸ n₂) , 2 * (n₁ ∸ n₂))) λ _ → ret triv)
+ ≤⟨ ≤⁻-refl ⟩
+ step⋆ (1 + 2 * (n₁ ∸ n₂) , 1 + 2 * (n₁ ∸ n₂))
+ ∎
+joinRight/is-bounded' {A} black (suc n₁) l₁ (black {y₁ = y₁₁} {y₂ = y₁₂} {l₁ = l₁₁} {l₂ = l₁₂} t₁₁ a₁ t₁₂) a y₂ n₂ l₂ t₂ n₁>n₂ with n₁ Nat.≟ n₂
+joinRight/is-bounded' black n₁ _ (black _ _ _) _ red _ _ (red _ _ _) _ | yes refl =
+ step⋆-mono-≤⁻ (Nat.z≤n {2 * (suc n₁ ∸ n₁)} , Nat.z≤n {2 * (suc n₁ ∸ n₁)})
+joinRight/is-bounded' black n₁ _ (black {y₂ = red} _ _ (red _ _ _)) _ black _ _ _ _ | yes refl =
+ step⋆-mono-≤⁻ (Nat.z≤n {2 * (suc n₁ ∸ n₁)} , Nat.z≤n {2 * (suc n₁ ∸ n₁)})
+joinRight/is-bounded' black n₁ _ (black {y₂ = black} _ _ _) _ black _ _ _ _ | yes refl =
+ step⋆-mono-≤⁻ (Nat.z≤n {2 * (suc n₁ ∸ n₁)} , Nat.z≤n {2 * (suc n₁ ∸ n₁)})
+... | no n₁≢n₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ step cost (1 , 1) (
+ bind cost (
+ bind (F (Σ⁺ (list A) (λ l → (meta⁺ (l ≡ (l₁₁ ++ a₁ ∷ l₁₂) ++ a ∷ l₂)) ×⁺ (arrbt A black (suc n₁) l))))
+ (joinRight _ _ _ t₁₂ a _ _ _ t₂ (Nat.≤∧≢⇒< (Nat.≤-pred n₁>n₂) (≢-sym n₁≢n₂)))
+ (joinRightContCase₂ l₁₁ l₁₂ l₂ a a₁ y₁₁ y₁₂ n₁ t₁₁))
+ (λ _ → ret triv))
+ ≡⟨ Eq.cong
+ (λ e → step cost (1 , 1) e)
+ (Eq.cong
+ (λ f → bind cost (joinRight _ _ _ t₁₂ a _ _ _ t₂ (Nat.≤∧≢⇒< (Nat.≤-pred n₁>n₂) (≢-sym n₁≢n₂))) f)
+ (funext (λ { (_ , _ , violation _ _ (red _ _ _)) → refl
+ ; (_ , _ , valid _) → refl }))) ⟩
+ step cost (1 , 1) (
+ bind cost (joinRight _ _ _ t₁₂ a _ _ _ t₂ (Nat.≤∧≢⇒< (Nat.≤-pred n₁>n₂) (≢-sym n₁≢n₂)))
+ (λ _ → ret triv))
+ ≤⟨ ≤⁻-mono (λ e → step cost (1 , 1) e) (joinRight/is-bounded _ _ _ t₁₂ a _ _ _ t₂ _) ⟩
+ step cost (1 , 1) (
+ bind cost (step⋆ (1 + 2 * (n₁ ∸ n₂) , 1 + 2 * (n₁ ∸ n₂))) λ _ → ret triv)
+ ≡⟨ Eq.cong (λ c → step⋆ c)
+ (Eq.cong₂ _,_
+ (Eq.trans (Eq.sym (Nat.*-suc 2 (n₁ ∸ n₂))) (Eq.cong (2 *_) (Eq.sym (Nat.+-∸-assoc 1 n₁>n₂))))
+ (Eq.trans (Eq.sym (Nat.*-suc 2 (n₁ ∸ n₂))) (Eq.cong (2 *_) (Eq.sym (Nat.+-∸-assoc 1 n₁>n₂))))) ⟩
+ step⋆ (2 * (suc n₁ ∸ n₂) , 2 * (suc n₁ ∸ n₂))
+ ∎
+
+joinRight/is-bounded red n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂ =
+ joinRight/is-bounded' red n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂
+joinRight/is-bounded black n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (joinRight black n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂) (λ _ → ret triv)
+ ≤⟨ joinRight/is-bounded' black n₁ l₁ t₁ a y₂ n₂ l₂ t₂ n₁>n₂ ⟩
+ step⋆ (2 * (n₁ ∸ n₂) , 2 * (n₁ ∸ n₂))
+ ≤⟨ step⋆-mono-≤⁻ (Nat.n≤1+n _ , Nat.n≤1+n _) ⟩
+ step⋆ (1 + 2 * (n₁ ∸ n₂) , 1 + 2 * (n₁ ∸ n₂))
+ ∎
+
+i-joinContCaseLeft : ∀ l₁ l₂ a y₂ n₁ n₂ n₁n₂ →
+ (Σ (List (val A)) (λ a₁ → Σ (a₁ ≡ l₁ ++ a ∷ l₂) (λ x → AlmostRightRBT A y₁ n₁ a₁))) →
+ cmp (F (Σ⁺ color (λ y → Σ⁺ (list A) (λ l → meta⁺ (l ≡ l₁ ++ a ∷ l₂) ×⁺ (irbt A y (suc (n₁ ⊔ n₂)) l ⊎⁺ irbt A y (n₁ ⊔ n₂) l)))))
+i-joinContCaseRight {A} l₁ l₂ a y₁ n₁ n₂ n₁>n₂ (l , l≡l₁++a∷l₂ , violation {l₁ = l'₁} {l₂ = l'₂} t'₁ a' t'₂) =
+ ret (black , l'₁ ++ [ a' ] ++ l'₂ , l≡l₁++a∷l₂ ,
+ inj₁ (Eq.subst (λ n → IRBT A black (suc n) (l'₁ ++ a' ∷ l'₂)) (Eq.sym (Nat.m≥n⇒m⊔n≡m (Nat.<⇒≤ n₁>n₂)))
+ (black t'₁ a' t'₂)))
+i-joinContCaseRight {A} l₁ l₂ a y₁ n₁ n₂ n₁>n₂ (l , l≡l₁++a∷l₂ , valid {n = n} {y = y} {l = l} t') =
+ ret (y , l , l≡l₁++a∷l₂ , inj₂ (Eq.subst (λ n → IRBT A y n l) (Eq.sym (Nat.m≥n⇒m⊔n≡m (Nat.<⇒≤ n₁>n₂))) t'))
+
+i-join :
+ cmp
+ ( Π color λ y₁ → Π nat λ n₁ → Π (list A) λ l₁ → Π (irbt A y₁ n₁ l₁) λ _ →
+ Π A λ a →
+ Π color λ y₂ → Π nat λ n₂ → Π (list A) λ l₂ → Π (irbt A y₂ n₂ l₂) λ _ →
+ F (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l)))
+ )
+i-join {A} y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ with Nat.<-cmp n₁ n₂
+i-join {A} red n₁ l₁ t₁ a y₂ n₂ l₂ t₂ | tri≈ ¬n₁n₂ =
+ ret (black , l₁ ++ [ a ] ++ l₂ , refl ,
+ inj₁ (Eq.subst (λ n → IRBT A black (suc n) (l₁ ++ a ∷ l₂)) (Eq.sym (Nat.⊔-idem n₁)) (black t₁ a t₂)))
+i-join {A} black n₁ l₁ t₁ a red n₂ l₂ t₂ | tri≈ ¬n₁n₂ =
+ ret (black , l₁ ++ [ a ] ++ l₂ , refl ,
+ inj₁ (Eq.subst (λ n → IRBT A black (suc n) (l₁ ++ a ∷ l₂)) (Eq.sym (Nat.⊔-idem n₁)) (black t₁ a t₂)))
+i-join {A} black n₁ l₁ t₁ a black n₂ l₂ t₂ | tri≈ ¬n₁n₂ =
+ ret (red , l₁ ++ [ a ] ++ l₂ , refl ,
+ inj₂ (Eq.subst (λ n → IRBT A red n (l₁ ++ a ∷ l₂)) (Eq.sym (Nat.⊔-idem n₁)) (red t₁ a t₂)))
+... | tri< n₁n₂ =
+ bind (F (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l))))
+ (joinLeft _ _ _ t₁ a _ _ _ t₂ n₁ ¬n₁n₂ =
+ bind (F (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l))))
+ (joinRight _ _ _ t₁ a _ _ _ t₂ n₁>n₂)
+ (i-joinContCaseRight l₁ l₂ a y₁ n₁ n₂ n₁>n₂)
+
+i-join/is-bounded : ∀ {A} y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂
+ → IsBounded (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l))) (i-join y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂)
+ (1 + (2 * (n₁ Nat.⊔ n₂ ∸ n₁ Nat.⊓ n₂)) , 1 + (2 * (n₁ Nat.⊔ n₂ ∸ n₁ Nat.⊓ n₂)))
+i-join/is-bounded {A} y₁ n₁ l₁ t₁ a y₂ n₂ l₂ t₂ with Nat.<-cmp n₁ n₂
+i-join/is-bounded {A} red n₁ l₁ t₁ a y₂ .n₁ l₂ t₂ | tri≈ ¬n₁n₂ =
+ step⋆-mono-≤⁻ (Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))}, Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))})
+i-join/is-bounded {A} black n₁ l₁ t₁ a red n₁ l₂ t₂ | tri≈ ¬n₁n₂ =
+ step⋆-mono-≤⁻ (Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))}, Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))})
+i-join/is-bounded {A} black n₁ l₁ t₁ a black n₁ l₂ t₂ | tri≈ ¬n₁n₂ =
+ step⋆-mono-≤⁻ (Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))}, Nat.z≤n {1 + (2 * (n₁ Nat.⊔ n₁ ∸ n₁ Nat.⊓ n₁))})
+... | tri< n₁n₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (
+ bind (F (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l))))
+ (joinLeft _ _ _ t₁ a _ _ _ t₂ n₁ ¬n₁n₂ =
+ let open ≤⁻-Reasoning cost in
+ begin
+ bind cost (
+ bind (F (Σ⁺ color λ y → Σ⁺ (list A) λ l →
+ (meta⁺ (l ≡ l₁ ++ [ a ] ++ l₂)) ×⁺ ((irbt A y (1 + (n₁ Nat.⊔ n₂)) l) ⊎⁺ (irbt A y (n₁ Nat.⊔ n₂) l))))
+ (joinRight _ _ _ t₁ a _ _ _ t₂ n₁>n₂)
+ (i-joinContCaseRight l₁ l₂ a y₁ n₁ n₂ n₁>n₂))
+ (λ _ → ret triv)
+ ≡⟨ Eq.cong
+ (λ f → bind cost (joinRight _ _ _ t₁ a _ _ _ t₂ n₁>n₂) f)
+ (funext (λ { (_ , _ , violation _ _ _) → refl
+ ; (_ , _ , valid _) → refl })) ⟩
+ bind cost (joinRight _ _ _ t₁ a _ _ _ t₂ n₁>n₂) (λ _ → ret triv)
+ ≤⟨ joinRight/is-bounded _ _ _ t₁ a _ _ _ t₂ n₁>n₂ ⟩
+ step⋆ (1 + 2 * (n₁ ∸ n₂) , 1 + 2 * (n₁ ∸ n₂))
+ ≡⟨ Eq.cong (λ c → step⋆ c)
+ (Eq.cong₂ _,_
+ (Eq.cong (1 +_) (Eq.cong (2 *_) (Eq.cong₂ _∸_ (Eq.sym (Nat.m≥n⇒m⊔n≡m (Nat.<⇒≤ n₁>n₂))) (Eq.sym (Nat.m≥n⇒m⊓n≡n (Nat.<⇒≤ n₁>n₂))))))
+ (Eq.cong (1 +_) (Eq.cong (2 *_) (Eq.cong₂ _∸_ (Eq.sym (Nat.m≥n⇒m⊔n≡m (Nat.<⇒≤ n₁>n₂))) (Eq.sym (Nat.m≥n⇒m⊓n≡n (Nat.<⇒≤ n₁>n₂))))))) ⟩
+ step⋆ (1 + (2 * (n₁ Nat.⊔ n₂ ∸ n₁ Nat.⊓ n₂)) , 1 + (2 * (n₁ Nat.⊔ n₂ ∸ n₁ Nat.⊓ n₂)))
+ ∎
+
+i-nodes : {y : val color} {n : val nat} {l : val (list A)} → IRBT A y n l → val nat
+i-nodes leaf = 0
+i-nodes (red t₁ _ t₂) = 1 + (i-nodes t₁) + (i-nodes t₂)
+i-nodes (black t₁ _ t₂) = 1 + (i-nodes t₁) + (i-nodes t₂)
+
+i-nodes≡lengthl : ∀ {y} {n} {l} → (t : IRBT A y n l) → i-nodes t ≡ length l
+i-nodes≡lengthl leaf = refl
+i-nodes≡lengthl (red {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ begin
+ 1 + (i-nodes t₁) + (i-nodes t₂)
+ ≡⟨ Eq.cong₂ _+_ (Eq.cong₂ _+_ refl (i-nodes≡lengthl t₁)) (i-nodes≡lengthl t₂) ⟩
+ 1 + length l₁ + length l₂
+ ≡⟨ Eq.cong₂ _+_ (Nat.+-comm 1 (length l₁)) refl ⟩
+ (length l₁ + 1) + length l₂
+ ≡⟨ Nat.+-assoc (length l₁) 1 (length l₂) ⟩
+ length l₁ + (1 + length l₂)
+ ≡⟨⟩
+ length l₁ + length ([ a ] ++ l₂)
+ ≡˘⟨ List.length-++ l₁ ⟩
+ length (l₁ ++ [ a ] ++ l₂)
+ ∎
+ where open ≡-Reasoning
+i-nodes≡lengthl (black {l₁ = l₁} {l₂ = l₂} t₁ a t₂) =
+ begin
+ 1 + (i-nodes t₁) + (i-nodes t₂)
+ ≡⟨ Eq.cong₂ _+_ (Eq.cong₂ _+_ refl (i-nodes≡lengthl t₁)) (i-nodes≡lengthl t₂) ⟩
+ 1 + length l₁ + length l₂
+ ≡⟨ Eq.cong₂ _+_ (Nat.+-comm 1 (length l₁)) refl ⟩
+ (length l₁ + 1) + length l₂
+ ≡⟨ Nat.+-assoc (length l₁) 1 (length l₂) ⟩
+ length l₁ + (1 + length l₂)
+ ≡⟨⟩
+ length l₁ + length ([ a ] ++ l₂)
+ ≡˘⟨ List.length-++ l₁ ⟩
+ length (l₁ ++ [ a ] ++ l₂)
+ ∎
+ where open ≡-Reasoning
+
+i-total-height : {y : val color} {n : val nat} {l : val (list A)} → IRBT A y n l → val nat
+i-total-height leaf = 0
+i-total-height (red t₁ _ t₂) = 1 + (i-total-height t₁ Nat.⊔ i-total-height t₂)
+i-total-height (black t₁ _ t₂) = 1 + (i-total-height t₁ Nat.⊔ i-total-height t₂)
+
+i-nodes/bound/node-black-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → 1 + (i-nodes t) Nat.≥ (2 Nat.^ n)
+i-nodes/bound/node-black-height leaf = Nat.s≤s Nat.z≤n
+i-nodes/bound/node-black-height (red {n} t₁ _ t₂) =
+ let open Nat.≤-Reasoning in
+ begin
+ 2 Nat.^ n
+ ≤⟨ i-nodes/bound/node-black-height t₁ ⟩
+ suc (i-nodes t₁)
+ ≤⟨ Nat.m≤m+n (suc (i-nodes t₁)) (suc (i-nodes t₂)) ⟩
+ (suc (i-nodes t₁)) + (suc (i-nodes t₂))
+ ≡⟨ Eq.cong suc (Nat.+-suc (i-nodes t₁) (i-nodes t₂)) ⟩
+ suc (suc (i-nodes t₁ + i-nodes t₂))
+ ∎
+i-nodes/bound/node-black-height (black {n} t₁ _ t₂) =
+ let open Nat.≤-Reasoning in
+ begin
+ (2 Nat.^ n) + ((2 Nat.^ n) + zero)
+ ≡⟨ Eq.sym (Eq.trans (Eq.sym (Nat.+-identityʳ ((2 Nat.^ n) + (2 Nat.^ n)))) (Nat.+-assoc ((2 Nat.^ n)) ((2 Nat.^ n)) 0)) ⟩
+ (2 Nat.^ n) + (2 Nat.^ n)
+ ≤⟨ Nat.+-monoʳ-≤ (2 Nat.^ n) (i-nodes/bound/node-black-height t₂) ⟩
+ (2 Nat.^ n) + (suc (i-nodes t₂))
+ ≤⟨ Nat.+-monoˡ-≤ ((suc (i-nodes t₂))) (i-nodes/bound/node-black-height t₁) ⟩
+ (suc (i-nodes t₁)) + (suc (i-nodes t₂))
+ ≡⟨ Eq.cong suc (Nat.+-suc (i-nodes t₁) (i-nodes t₂)) ⟩
+ suc (suc (i-nodes t₁ + i-nodes t₂))
+ ∎
+
+i-nodes/bound/log-node-black-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → n Nat.≤ ⌈log₂ (1 + (i-nodes t)) ⌉
+i-nodes/bound/log-node-black-height {A} {y} {n} t =
+ let open Nat.≤-Reasoning in
+ begin
+ n
+ ≡⟨ Eq.sym (⌈log₂2^n⌉≡n n) ⟩
+ ⌈log₂ (2 Nat.^ n) ⌉
+ ≤⟨ ⌈log₂⌉-mono-≤ (i-nodes/bound/node-black-height t) ⟩
+ ⌈log₂ (1 + (i-nodes t)) ⌉
+ ∎
+
+total-height/black-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → (i-total-height t) Nat.≤ (2 * n + 1)
+total-height/black-height leaf = Nat.z≤n
+total-height/black-height (red leaf _ leaf) = Nat.s≤s Nat.z≤n
+total-height/black-height (red (black {n} t₁₁ _ t₁₂) _ (black t₂₁ _ t₂₂)) =
+ let open Nat.≤-Reasoning in
+ begin
+ suc (suc ((i-total-height t₁₁ Nat.⊔ i-total-height t₁₂) Nat.⊔ (i-total-height t₂₁ Nat.⊔ i-total-height t₂₂)))
+ ≤⟨ Nat.s≤s (Nat.s≤s (Nat.⊔-mono-≤ (Nat.⊔-mono-≤ (total-height/black-height t₁₁) (total-height/black-height t₁₂)) (Nat.⊔-mono-≤ (total-height/black-height t₂₁) (total-height/black-height t₂₂)))) ⟩
+ suc (suc (((2 * n + 1) Nat.⊔ (2 * n + 1)) Nat.⊔ ((2 * n + 1) Nat.⊔ (2 * n + 1))))
+ ≡⟨ Eq.cong suc (Eq.cong suc (Nat.m≤n⇒m⊔n≡n Nat.≤-refl)) ⟩
+ suc (suc ((2 * n + 1) Nat.⊔ (2 * n + 1)))
+ ≡⟨ Eq.cong suc (Eq.cong suc (Nat.m≤n⇒m⊔n≡n Nat.≤-refl)) ⟩
+ suc (suc (2 * n + 1))
+ ≡⟨ Eq.cong suc (Eq.trans (Eq.cong suc (Nat.+-assoc n (n + zero) 1)) (Eq.sym (Nat.+-suc n ((n + zero) + 1)))) ⟩
+ suc (n + suc ((n + zero) + 1))
+ ≡⟨ Eq.cong suc (Eq.sym (Nat.+-assoc n (suc (n + zero)) 1)) ⟩
+ 2 * (suc n) + 1
+ ∎
+total-height/black-height (black {n} t₁ _ t₂) =
+ let open Nat.≤-Reasoning in
+ begin
+ suc (i-total-height t₁ Nat.⊔ i-total-height t₂)
+ ≤⟨ Nat.s≤s (Nat.⊔-mono-≤ (total-height/black-height t₁) (total-height/black-height t₂)) ⟩
+ suc ((2 * n + 1) Nat.⊔ (2 * n + 1))
+ ≡⟨ Eq.cong suc (Nat.m≤n⇒m⊔n≡n Nat.≤-refl) ⟩
+ suc (2 * n + 1)
+ ≤⟨ Nat.s≤s (Nat.+-monoˡ-≤ 1 (Nat.+-monoʳ-≤ n (Nat.n≤1+n (n + zero)))) ⟩
+ 2 * (suc n) + 1
+ ∎
+
+i-nodes/bound/total-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → (1 + (i-nodes t)) Nat.≤ (2 Nat.^ (i-total-height t))
+i-nodes/bound/total-height leaf = Nat.s≤s Nat.z≤n
+i-nodes/bound/total-height (red t₁ _ t₂) =
+ let open Nat.≤-Reasoning in
+ begin
+ suc (suc (i-nodes t₁ + i-nodes t₂))
+ ≡⟨ Eq.cong suc (Eq.sym (Nat.+-suc (i-nodes t₁) (i-nodes t₂))) ⟩
+ (suc (i-nodes t₁) + (suc (i-nodes t₂)))
+ ≤⟨ Nat.+-monoˡ-≤ (suc (i-nodes t₂)) (i-nodes/bound/total-height t₁) ⟩
+ (2 Nat.^ (i-total-height t₁)) + (suc (i-nodes t₂))
+ ≤⟨ Nat.+-monoʳ-≤ (2 Nat.^ (i-total-height t₁)) (i-nodes/bound/total-height t₂) ⟩
+ (2 Nat.^ (i-total-height t₁)) + (2 Nat.^ (i-total-height t₂))
+ ≤⟨ Nat.+-monoˡ-≤ ((2 Nat.^ (i-total-height t₂))) (Nat.^-monoʳ-≤ 2 {x = i-total-height t₁} (Nat.m≤n⇒m≤n⊔o (i-total-height t₂) (Nat.≤-refl))) ⟩
+ (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₂))
+ ≤⟨ Nat.+-monoʳ-≤ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) ((Nat.^-monoʳ-≤ 2 {x = i-total-height t₂} (Nat.m≤n⇒m≤o⊔n (i-total-height t₁) (Nat.≤-refl)))) ⟩
+ (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))
+ ≡⟨ Eq.trans (Eq.sym (Nat.+-identityʳ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))))) (Nat.+-assoc ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) 0) ⟩
+ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + zero))
+ ∎
+i-nodes/bound/total-height (black t₁ _ t₂) =
+ let open Nat.≤-Reasoning in
+ begin
+ suc (suc (i-nodes t₁ + i-nodes t₂))
+ ≡⟨ Eq.cong suc (Eq.sym (Nat.+-suc (i-nodes t₁) (i-nodes t₂))) ⟩
+ (suc (i-nodes t₁) + (suc (i-nodes t₂)))
+ ≤⟨ Nat.+-monoˡ-≤ (suc (i-nodes t₂)) (i-nodes/bound/total-height t₁) ⟩
+ (2 Nat.^ (i-total-height t₁)) + (suc (i-nodes t₂))
+ ≤⟨ Nat.+-monoʳ-≤ (2 Nat.^ (i-total-height t₁)) (i-nodes/bound/total-height t₂) ⟩
+ (2 Nat.^ (i-total-height t₁)) + (2 Nat.^ (i-total-height t₂))
+ ≤⟨ Nat.+-monoˡ-≤ ((2 Nat.^ (i-total-height t₂))) (Nat.^-monoʳ-≤ 2 {x = i-total-height t₁} (Nat.m≤n⇒m≤n⊔o (i-total-height t₂) (Nat.≤-refl))) ⟩
+ (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₂))
+ ≤⟨ Nat.+-monoʳ-≤ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) ((Nat.^-monoʳ-≤ 2 {x = i-total-height t₂} (Nat.m≤n⇒m≤o⊔n (i-total-height t₁) (Nat.≤-refl)))) ⟩
+ (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))
+ ≡⟨ Eq.trans (Eq.sym (Nat.+-identityʳ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + (2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))))) (Nat.+-assoc ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂))) 0) ⟩
+ ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + ((2 Nat.^ (i-total-height t₁ Nat.⊔ i-total-height t₂)) + zero))
+ ∎
+
+i-nodes/lower-bound/node-black-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → (1 + (i-nodes t)) Nat.≤ (2 Nat.^ (2 * n + 1))
+i-nodes/lower-bound/node-black-height {A} {y} {n} t =
+ let open Nat.≤-Reasoning in
+ begin
+ 1 + (i-nodes t)
+ ≤⟨ i-nodes/bound/total-height t ⟩
+ 2 Nat.^ (i-total-height t)
+ ≤⟨ Nat.^-monoʳ-≤ 2 (total-height/black-height t) ⟩
+ 2 Nat.^ (2 * n + 1)
+ ∎
+
+i-nodes/lower-bound/log-node-black-height : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → n Nat.≥ ⌊ (⌈log₂ (1 + (i-nodes t)) ⌉ ∸ 1) /2⌋
+i-nodes/lower-bound/log-node-black-height {A} {y} {n} t =
+ let open Nat.≤-Reasoning in
+ begin
+ ⌊ (⌈log₂ (1 + (i-nodes t)) ⌉ ∸ 1) /2⌋
+ ≤⟨ Nat.⌊n/2⌋-mono (h t) ⟩
+ ⌊ (2 * n) /2⌋
+ ≡⟨ Eq.sym (Eq.trans (Nat.n≡⌊n+n/2⌋ n) (Eq.cong ⌊_/2⌋ (Eq.cong₂ _+_ refl (Eq.sym (Nat.+-identityʳ n))))) ⟩
+ n
+ ∎
+ where
+ m≤o+n⇒m∸n≤o : (m n o : val nat) → (m Nat.≤ (o + n)) → ((m ∸ n) Nat.≤ o)
+ m≤o+n⇒m∸n≤o m n o m≤o+n =
+ let open Nat.≤-Reasoning in
+ begin
+ m ∸ n
+ ≤⟨ Nat.∸-monoˡ-≤ n m≤o+n ⟩
+ (o + n) ∸ n
+ ≡⟨ Nat.m+n∸n≡m o n ⟩
+ o
+ ∎
+
+ h : {y : val color} {n : val nat} {l : val (list A)} → (t : IRBT A y n l) → (⌈log₂ (1 + (i-nodes t)) ⌉ ∸ 1) Nat.≤ (2 * n)
+ h {y} {n} t = m≤o+n⇒m∸n≤o ⌈log₂ (1 + (i-nodes t)) ⌉ 1 (2 * n) (
+ let open Nat.≤-Reasoning in
+ begin
+ ⌈log₂ (1 + (i-nodes t)) ⌉
+ ≤⟨ ⌈log₂⌉-mono-≤ (i-nodes/lower-bound/node-black-height t) ⟩
+ ⌈log₂ (2 Nat.^ (2 * n + 1)) ⌉
+ ≡⟨ ⌈log₂2^n⌉≡n (2 * n + 1) ⟩
+ 2 * n + 1
+ ∎)
+
+
+i-rec : {A : tp⁺} {X : tp⁻} →
+ cmp
+ ( Π (U X) λ _ →
+ Π
+ ( U
+ ( Π color λ y₁ → Π nat λ n₁ → Π (list A) λ l₁ → Π (irbt A y₁ n₁ l₁) λ _ → Π (U X) λ _ →
+ Π A λ _ →
+ Π color λ y₂ → Π nat λ n₂ → Π (list A) λ l₂ → Π (irbt A y₂ n₂ l₂) λ _ → Π (U X) λ _ →
+ X
+ )
+ ) λ _ →
+ Π color λ y → Π nat λ n → Π (list A) λ l → Π (irbt A y n l) λ _ →
+ X
+ )
+i-rec {A} {X} z f .black .zero .[] leaf = z
+i-rec {A} {X} z f .red n .(_ ++ [ a ] ++ _) (red t₁ a t₂) =
+ f
+ _ _ _ t₁ (i-rec {A} {X} z f _ _ _ t₁)
+ a
+ _ _ _ t₂ (i-rec {A} {X} z f _ _ _ t₂)
+i-rec {A} {X} z f .black .(suc _) .(_ ++ [ a ] ++ _) (black t₁ a t₂) =
+ f
+ _ _ _ t₁ (i-rec {A} {X} z f _ _ _ t₁)
+ a
+ _ _ _ t₂ (i-rec {A} {X} z f _ _ _ t₂)