open import DynamicallyChecked.Universe
open import Data.Nat as Nat

module HoareLogic.Examples.Alignment (Sᵁ Vᵁ : {n : }  U n) where

open import DynamicallyChecked.Utilities
open import DynamicallyChecked.Partiality
open import DynamicallyChecked.Rearrangement
open import DynamicallyChecked.BiGUL
open import HoareLogic.Utilities
open import HoareLogic.Semantics
open import HoareLogic.Rearrangement
open import HoareLogic.Triple

open import Function
open import Data.Empty using (⊥-elim)
open import Data.Product as Product
open import Data.Sum
open import Data.Bool
open import Data.Nat.Properties
open import Data.List as List
open import Data.List.Any as Any
open import Data.Fin using (Fin; zero; suc; toℕ)
open import Relation.Nullary
open import Relation.Nullary.Decidable
open import Relation.Binary
open import Relation.Binary.PropositionalEquality


F : Functor 2
F zero       = one  (Sᵁ  var zero)
F (suc zero) = one  (Vᵁ  var (suc zero))
F (suc (suc ()))

S : Set
S =  Sᵁ  (μ F)

V : Set
V =  Vᵁ  (μ F)

ListS : Set
ListS = μ F zero

ListV : Set
ListV = μ F (suc zero)

pattern []ᴹ       = con (inj₁ tt)
pattern _∷ᴹ_ x xs = con (inj₂ (x , xs))

infixr 5 _∷ᴹ_

toList₀ : ListS  List S
toList₀ []ᴹ       = []
toList₀ (s ∷ᴹ ss) = s  toList₀ ss

toList₁ : ListV  List V
toList₁ []ᴹ       = []
toList₁ (v ∷ᴹ vs) = v  toList₁ vs

extract : {K : Set}  Decidable (_≡_ {A = K})  (S  K)  (V  K)  V  ListS  ListS
extract keq ks kv v []ᴹ       = []ᴹ
extract keq ks kv v (s ∷ᴹ ss) with keq (ks s) (kv v)
extract keq ks kv v (s ∷ᴹ ss) | yes _ = s ∷ᴹ ss
extract keq ks kv v (s ∷ᴹ ss) | no  _ with extract keq ks kv v ss
extract keq ks kv v (s ∷ᴹ ss) | no  _ | []ᴹ         = s ∷ᴹ []ᴹ
extract keq ks kv v (s ∷ᴹ ss) | no  _ | (s' ∷ᴹ ss') = s' ∷ᴹ s ∷ᴹ ss'

headMatch : {K : Set}  Decidable (_≡_ {A = K})  (S  K)  (V  K)  ListS  ListV  Bool
headMatch keq ks kv (s ∷ᴹ _) (v ∷ᴹ _) =  keq (ks s) (kv v) 
headMatch keq ks kv _        _        = false

keyAlignᴮ : {K : Set}  Decidable (_≡_ {A = K})  (S  K)  (V  K)  BiGUL F Sᵁ Vᵁ  (V  S) 
            BiGUL F (var zero) (var (suc zero))  BiGUL F (var zero) (var (suc zero))
keyAlignᴮ keq ks kv b c rec = case
  (((λ { []ᴹ []ᴹ  true; _ _  false }) ,
    normal
      (rearrV (con (left (k tt))) (k {G = one} tt) tt (return refl)
         (skip (const tt)))
       { []ᴹ  true; _  false })) 
   (headMatch keq ks kv ,
    normal
      (rearrS (con (right (prod var var))) (prod var var) (inj₁ refl , inj₂ refl) (return refl >>= return refl)
         (rearrV (con (right (prod var var))) (prod var var) ((inj₁ refl , inj₂ refl)) (return refl >>= return refl)
            (prod b rec)))
       { (_ ∷ᴹ _)  true; _  false })) 
   ((λ { (_ ∷ᴹ _) []ᴹ  true ; _ _  false }) ,
    adaptive  _ _  []ᴹ)) 
   ((λ { ss (v ∷ᴹ _)   Any.any  s  keq (ks s) (kv v)) (toList₀ ss) ; _ _  false }) ,
    adaptive  { ss (v ∷ᴹ _)  extract keq ks kv v ss; ss _  ss })) 
   ((λ { _ (_ ∷ᴹ _)  true; _ _  false }) ,
    adaptive  { ss (v ∷ᴹ _)  c v ∷ᴹ ss; ss _  ss } ))  [])

data Elementwise {A B C : Set} (R :  (A × B × C)) :  (List A × List B × List C) where
  []  : Elementwise R ([] , [] , [])
  _∷_ : {x : A} {y : B} {z : C}  R (x , y , z) 
        {xs : List A} {ys : List B} {zs : List C}  Elementwise R (xs , ys , zs) 
        Elementwise R (x  xs , y  ys , z  zs)

data Count {A : Set} (P :  A) :  ( × List A) where
  []   : Count P (zero , [])
  _∷ʸ_ : {x : A}    P x  {n : } {xs : List A}  Count P (n , xs)  Count P (suc n , x  xs)
  _∷ⁿ_ : {x : A}  ¬ P x  {n : } {xs : List A}  Count P (n , xs)  Count P (    n , x  xs)

Post : {K : Set}  (S  K)  (V  K)   (S × S × V)   (ListS × ListS × ListV)
Post ks kv R' (ss' , ss , vs) = 
  Σ[ ssᴹ  List S ]
    Elementwise  { (s' , s , v)  R' (s' , s , v) × ks s'  kv v }) (toList₀ ss' , ssᴹ , toList₁ vs) ×
    ((s : S) (i : Any (s ≡_) (toList₀ ss))
     (m : )  Count ((ks s ≡_)  ks) (m , take (toℕ (index i)) (toList₀ ss)) 
     (n : )  Count ((ks s ≡_)  kv) (n , toList₁ vs) 
     m < n  Any (s ≡_) ssᴹ)

extract-reentry :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (ss : ListS) (v : V) (vs : ListV) 
  Any  s  ks s  kv v) (toList₀ ss)  headMatch keq ks kv (extract keq ks kv v ss) (v ∷ᴹ vs)  true
extract-reentry keq ks kv []ᴹ       v vs ()
extract-reentry keq ks kv (s ∷ᴹ ss) v vs i                with keq (ks s) (kv v)
extract-reentry keq ks kv (s ∷ᴹ ss) v vs i                | yes ks-s≡kv-v = trueFromWitness ks-s≡kv-v
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (here ks-s≡kv-v) | no  ks-s≢kv-v with ks-s≢kv-v ks-s≡kv-v
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (here ks-s≡kv-v) | no  ks-s≢kv-v | ()
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (there i       ) | no  ks-s≢kv-v with extract-reentry keq ks kv ss v vs i
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (there i       ) | no  ks-s≢kv-v | rec with extract keq ks kv v ss
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (there i       ) | no  ks-s≢kv-v | ()  | []ᴹ
extract-reentry keq ks kv (s ∷ᴹ ss) v vs (there i       ) | no  ks-s≢kv-v | rec | s' ∷ᴹ ss' = rec

extract-reindex : 
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (ss : ListS) (v : V) (s* : S) 
  Any (s* ≡_) (toList₀ ss)  Any (s* ≡_) (toList₀ (extract keq ks kv v ss))
extract-reindex keq ks kv []ᴹ       v s*  ()
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  i           with keq (ks s) (kv v)
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  i           | yes ks-s≡kv-v = i
extract-reindex keq ks kv (s ∷ᴹ ss) v .s  (here refl) | no  ks-s≢kv-v with extract keq ks kv v ss
extract-reindex keq ks kv (s ∷ᴹ ss) v .s  (here refl) | no  ks-s≢kv-v | []ᴹ       = here refl
extract-reindex keq ks kv (s ∷ᴹ ss) v .s  (here refl) | no  ks-s≢kv-v | s' ∷ᴹ ss' = there (here refl)
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  (there i  ) | no  ks-s≢kv-v with extract-reindex keq ks kv ss v s* i
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  (there i  ) | no  ks-s≢kv-v | rec with extract keq ks kv v ss
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  (there i  ) | no  ks-s≢kv-v | ()  | []ᴹ
extract-reindex keq ks kv (s ∷ᴹ ss) v .s' (there i  ) | no  ks-s≢kv-v | (here refl) | s' ∷ᴹ ss' = here refl
extract-reindex keq ks kv (s ∷ᴹ ss) v s*  (there i  ) | no  ks-s≢kv-v | (there j  ) | s' ∷ᴹ ss' = there (there j)

extract-head :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (ss : ListS) (v : V) 
  Any ((_≡ kv v)  ks) (toList₀ ss)  Σ (S × ListS) λ { (s' , ss')  extract keq ks kv v ss  s' ∷ᴹ ss' × ks s'  kv v }
extract-head keq ks kv []ᴹ       v () 
extract-head keq ks kv (s ∷ᴹ ss) v i                with keq (ks s) (kv v)
extract-head keq ks kv (s ∷ᴹ ss) v i                | yes ks-s≡kv-v = (s , ss) , refl , ks-s≡kv-v
extract-head keq ks kv (s ∷ᴹ ss) v (here ks-s≡kv-v) | no  ks-s≢kv-v with ks-s≢kv-v ks-s≡kv-v
extract-head keq ks kv (s ∷ᴹ ss) v (here ks-s≡kv-v) | no  ks-s≢kv-v | ()
extract-head keq ks kv (s ∷ᴹ ss) v (there i)        | no  ks-s≢kv-v with extract-head keq ks kv ss v i
extract-head keq ks kv (s ∷ᴹ ss) v (there i)        | no  ks-s≢kv-v | rec             with extract keq ks kv v ss
extract-head keq ks kv (s ∷ᴹ ss) v (there i)        | no  ks-s≢kv-v | (_ , () , _)    | []ᴹ
extract-head keq ks kv (s ∷ᴹ ss) v (there i)        | no  ks-s≢kv-v | (_ , refl , eq) | s' ∷ᴹ ss' = _ , refl , eq

extract-Count : 
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (ss : ListS) (v : V) 
  Any ((_≡ kv v)  ks) (toList₀ ss)  (s* : S) (i : Any (s* ≡_) (toList₀ ss)) {m : } 
  Count  s  ks s*  ks s) (m , take (toℕ (index i)) (toList₀ ss)) 
  Count  s  ks s*  ks s) (m , take (toℕ (index (extract-reindex keq ks kv ss v s* i)))
                                       (toList₀ (extract keq ks kv v ss)))
extract-Count keq ks kv []ᴹ       v e                s* ()          c
extract-Count keq ks kv (s ∷ᴹ ss) v e                s* i           c with keq (ks s) (kv v)
extract-Count keq ks kv (s ∷ᴹ ss) v e                s* i           c | yes ks-s≡kv-v = c
extract-Count keq ks kv (s ∷ᴹ ss) v (here ks-s≡kv-v) s* i           c | no  ks-s≢kv-v with ks-s≢kv-v ks-s≡kv-v
extract-Count keq ks kv (s ∷ᴹ ss) v (here ks-s≡kv-v) s* i           c | no  ks-s≢kv-v | ()
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* i           c | no  ks-s≢kv-v
  with extract-head keq ks kv ss v e
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        .s (here refl) c | no  ks-s≢kv-v
  | h with extract keq ks kv v ss
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        .s (here refl) c | no  ks-s≢kv-v
  | h | []ᴹ       = c
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        .s (here refl) c | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | s' ∷ᴹ ss' =  ks-s≡ks-s'  ks-s≢kv-v (trans ks-s≡ks-s' ks-s'≡kv-v)) ∷ⁿ c
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | h with extract-Count keq ks kv ss v e s* i c
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | h | rec with extract-reindex keq ks kv ss v s* i
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | h | rec | j with extract keq ks kv v ss
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | h | rec | () | []ᴹ
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | rec | here refl | s' ∷ᴹ ss' with ks-s≢kv-v (trans (sym ks-s*≡ks-s) ks-s'≡kv-v)
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | rec | here refl | s' ∷ᴹ ss' | ()
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | ks-s*≡ks-s' ∷ʸ c' | there j | s' ∷ᴹ ss' = ks-s*≡ks-s' ∷ʸ (ks-s*≡ks-s ∷ʸ c')
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≡ks-s ∷ʸ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | ks-s*≢ks-s' ∷ⁿ c' | there j | s' ∷ᴹ ss' = ks-s*≢ks-s' ∷ⁿ (ks-s*≡ks-s ∷ʸ c')
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | h with extract-Count keq ks kv ss v e s* i c
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | h | rec with extract-reindex keq ks kv ss v s* i
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | h | rec | j with extract keq ks kv v ss
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | h | rec | () | []ᴹ
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | rec | here refl | s' ∷ᴹ ss' = rec
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | ks-s*≡ks-s' ∷ʸ c' | there j | s' ∷ᴹ ss' = ks-s*≡ks-s' ∷ʸ (ks-s*≢ks-s ∷ⁿ c')
extract-Count keq ks kv (s ∷ᴹ ss) v (there e)        s* (there i  ) (ks-s*≢ks-s ∷ⁿ c) | no  ks-s≢kv-v
  | ._ , refl , ks-s'≡kv-v | ks-s*≢ks-s' ∷ⁿ c' | there j | s' ∷ᴹ ss' = ks-s*≢ks-s' ∷ⁿ (ks-s*≢ks-s ∷ⁿ c')

keyAlign-correctness :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (b : BiGUL F Sᵁ Vᵁ) (c : V  S)
  (R' :  (S × S × V))  Triple  { (s , v)  ks s  kv v }) b (R'   { (s' , _ , v)  ks s'  kv v })) 
  ((v : V)  ks (c v)  kv v) 
  (n : ) (rec : BiGUL F (var zero) (var (suc zero))) 
  ({m : }  Triple (((_≡ m)  length  toList₁  proj₂)   _  m < n)) rec (Post ks kv R')) 
  Triple ((_≡ n)  length  toList₁  proj₂) (keyAlignᴮ keq ks kv b c rec) (Post ks kv R')
keyAlign-correctness keq ks kv b c R' b-t c-eq n rec rec-t =
  case
    (conseq  { {[]ᴹ    , []ᴹ   } _  tt , tt , refl
               ; {[]ᴹ    , _ ∷ᴹ _} (_ , () , _)
               ; {_ ∷ᴹ _ , []ᴹ   } (_ , () , _)
               ; {_ ∷ᴹ _ , _ ∷ᴹ _} (_ , () , _) })
            (rearrV  { ([]ᴹ , _)  ; (_ ∷ᴹ _ , _)   })  { ([]ᴹ , _)  ; (_ ∷ᴹ _ , _)   })
               (conseq  _  refl)
                       skip
                        { { .[]ᴹ   , []ᴹ    , _} (refl , _)  tt , tt , refl
                          ; {  []ᴹ   , _ ∷ᴹ _ , _} _  tt , tt , refl
                          ; { _ ∷ᴹ _ , _ ∷ᴹ _ , _} (_ , _ , () , _) })))
             { {[]ᴹ    , []ᴹ    , []ᴹ   } _  ([] , [] , λ _ ()) , (refl , tt) , refl , tt
               ; {_ ∷ᴹ _ , []ᴹ    , []ᴹ   } ((_ , () , _) , _)
               ; {_      , []ᴹ    , _ ∷ᴹ _} (_ , _ , () , _)
               ; {_      , _ ∷ᴹ _ , []ᴹ   } (_ , _ , () , _)
               ; {_      , _ ∷ᴹ _ , _ ∷ᴹ _} (_ , _ , () , _) }) ∷ᴺ
     conseq
        { {[]ᴹ    , []ᴹ   } (_ , () , _)
          ; {[]ᴹ    , _ ∷ᴹ _} (_ , () , _)
          ; {_ ∷ᴹ _ , []ᴹ   } (_ , () , _)
          ; {_ ∷ᴹ _ , _ ∷ᴹ _} (vlen , eqn , _)  _ , (refl , refl) , vlen , trueToWitness eqn })
       (rearrS  { ((s , ss) , []ᴹ    )  
                  ; ((s , ss) , v ∷ᴹ vs)  length (toList₁ (v ∷ᴹ vs))  n × ks s  kv v })
               (Post ks kv R'  Product.map (uncurry _∷ᴹ_) (Product.map (uncurry _∷ᴹ_) id))
          (conseq
              { {_ , []ᴹ   } (_ , _ , ())
                ; {_ , _ ∷ᴹ _} (_ , (refl , refl) , vlen , ks-s≡kv-v)  _ , (vlen , ks-s≡kv-v) , refl , refl })
             (rearrV  { ((s , ss) , (v , vs))  length (toList₁ (v ∷ᴹ vs))  n × ks s  kv v })
                     (Post ks kv R'  Product.map (uncurry _∷ᴹ_) (Product.map (uncurry _∷ᴹ_) (uncurry _∷ᴹ_)))
                (conseq
                    { (_ , (vlen , ks-s≡kv-v) , eq , vseq)  
                        trans ks-s≡kv-v (cong kv eq) ,
                        cong pred (subst  vs  suc (length (toList₁ vs))  n) vseq vlen) , pred-lemma vlen })
                   (prod b-t rec-t)
                    { {(s' , ss') , (s , ss) , (v , vs)}
                        (((R'-s'-s-v , ks-s'≡kv-v) , (ssᴹ , ew , ret)) , (v' , vs') , (_ , ks-s≡kv-v') , v'≡v , vs'≡vs) 
                          _ , (s  ssᴹ , (R'-s'-s-v , ks-s'≡kv-v)  ew ,
                               λ { sᴹ (here eq) m cm n cn m<n  here eq
                                 ; sᴹ (there i) (suc m) (ks-sᴹ≡ks-s ∷ʸ cm) (suc n) (ks-sᴹ≡kv-v ∷ʸ cn) (s≤s m<n) 
                                     there (ret sᴹ i m cm n cn m<n)
                                 ; sᴹ (there i) m (ks-sᴹ≡ks-s ∷ʸ cm) n (ks-sᴹ≢kv-v ∷ⁿ cn) m<n 
                                     ⊥-elim (ks-sᴹ≢kv-v (trans ks-sᴹ≡ks-s (trans ks-s≡kv-v' (cong kv v'≡v))))
                                 ; sᴹ (there i) m (ks-sᴹ≢ks-s ∷ⁿ cm) n (ks-sᴹ≡kv-v ∷ʸ cn) m<n 
                                     ⊥-elim (ks-sᴹ≢ks-s (trans ks-sᴹ≡kv-v (sym (trans ks-s≡kv-v' (cong kv v'≡v)))))
                                 ; sᴹ (there i) m (ks-sᴹ≢ks-s ∷ⁿ cm) n (ks-sᴹ≢kv-v ∷ⁿ cn) m<n 
                                     there (ret sᴹ i m cm n cn m<n) }) ,
                          refl , refl })))
              { {_ , _ , []ᴹ   } (_ , _ , _ , ())
                ; {_ , _ , _ ∷ᴹ _} ((_ , post , refl , refl) , _ , (refl , refl) , _) 
                    _ , post , (refl , refl) , refl , refl})))
        { {[]ᴹ , _} ((_ , _ , () , _) , _)
          ; {_ ∷ᴹ _ , []ᴹ , _} ((_ , _ , _ , ()) , _)
          ; {_ ∷ᴹ _ , _ ∷ᴹ _ , []ᴹ   } ((_ , _ , (refl , refl) , (refl , refl)) , _ , () , _)
          ; {_ ∷ᴹ _ , _ ∷ᴹ _ , _ ∷ᴹ _} ((_ , ([] , () , _) , _) , _)
          ; {_ ∷ᴹ _ , _ ∷ᴹ _ , _ ∷ᴹ _} ((_ , (sᴹ  ssᴹ , (r' , ks-s'≡kv-v)  ew , r) , (refl , refl) , (refl , refl)) , _) 
              (sᴹ  ssᴹ , (r' , ks-s'≡kv-v)  ew , r) , (trueFromWitness ks-s'≡kv-v , refl , tt) , refl , refl , tt }) ∷ᴺ
      { []ᴹ      []ᴹ      (_ , () , _)
        ; []ᴹ      (_ ∷ᴹ _) (_ , () , _)
        ; (_ ∷ᴹ _) []ᴹ      (vlen , _) 
            (vlen , inj₁ refl) ,
             { []ᴹ      _  [] , [] , λ { sᴹ i m cm (suc n) () (s≤s m≤n) }
               ; (_ ∷ᴹ _) (_ , () , _) })
        ; (_ ∷ᴹ _) (_ ∷ᴹ _) (_ , () , _) }) ∷ᴬ
      { _         []ᴹ       (_ , () , _)
        ; []ᴹ       (_ ∷ᴹ _)  (vlen , () , _)
        ; (s ∷ᴹ ss) (v ∷ᴹ vs) (vlen , anyeqn , _ , ks-s≢kv-v , _) 
            (vlen , inj₂ (inj₁ (extract-reentry keq ks kv (s ∷ᴹ ss) v vs (trueToWitness anyeqn)))) ,
            λ { ss' (ssᴹ , ew , ret) 
                  ssᴹ , ew ,
                  λ s* i m cm n cn m<n 
                      ret s* (extract-reindex keq ks kv (s ∷ᴹ ss) v s* i) m
                             (extract-Count keq ks kv (s ∷ᴹ ss) v (trueToWitness anyeqn) s* i cm) n cn m<n } }) ∷ᴬ
      { ss []ᴹ       (_ , () , _)
        ; ss (v ∷ᴹ vs) (vlen , _ , ¬any , _) 
            (vlen , inj₂ (inj₁ (trueFromWitness (c-eq v)))) ,
            λ { []ᴹ         (_ , () , _)
              ; (s' ∷ᴹ ss') (ssᴹ , ew , ret) 
                  ssᴹ , ew ,
                  λ s i m cm n cn m<n 
                    ret s (there i) m
                        ((λ ks-s≡ks-c-v 
                              falseToWitness ¬any
                                (Any.map  s≡x  trans (cong ks (sym s≡x)) (trans ks-s≡ks-c-v (c-eq v))) i)) ∷ⁿ cm)
                        n cn m<n } }) ∷ᴬ [])
     { {[]ᴹ    , []ᴹ   } _  inj₁ refl
       ; {_ ∷ᴹ _ , []ᴹ   } _  inj₂ (inj₂ (inj₁ refl))
       ; {_      , _ ∷ᴹ _} _  inj₂ (inj₂ (inj₂ (inj₂ (inj₁ refl)))) })

keyAlign-finite-expansion :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (b : BiGUL F Sᵁ Vᵁ) (c : V  S)
  (R' :  (S × S × V))  Triple  { (s , v)  ks s  kv v }) b (R'   { (s' , _ , v)  ks s'  kv v })) 
  ((v : V)  ks (c v)  kv v) 
  (l n : )  n  l  Triple ((_≡ n)  length  toList₁  proj₂)
                             (expand (suc l) (keyAlignᴮ keq ks kv b c))
                             (Post ks kv R')
keyAlign-finite-expansion keq ks kv b c R' b-t c-eq l n n≤l =
  conseq (_,_ tt)
         (expandTriple (keyAlignᴮ keq ks kv b c) (length  toList₁  proj₂) Π (Post ks kv R')
                        n rec rec-t  conseq proj₂
                                               (keyAlign-correctness keq ks kv b c R' b-t c-eq n rec
                                                  (conseq (_,_ tt) rec-t proj₁))
                                               proj₁)
                       l n n≤l)
         proj₁

keyAlign-range :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (b : BiGUL F Sᵁ Vᵁ) (c : V  S) 
  TripleR  { (s , v)  ks s  kv v }) b Π 
  (n : ) (rec : BiGUL F (var zero) (var (suc zero))) 
  ({m : }  TripleR (((_≡ m)  length  toList₁  proj₂)) rec
                     (((_≡ m)  length  toList₀)   _  m < n))) 
  TripleR ((_≡ n)  length  toList₁  proj₂) (keyAlignᴮ keq ks kv b c rec) ((_≡ n)  length  toList₀)
keyAlign-range keq ks kv b c b-t n rec rec-t =
  conseq
    proj₁
    (case
       ((conseq
            { {[]ᴹ    , []ᴹ   } (_ , 0≡n)  0≡n , refl , tt
              ; {[]ᴹ    , _ ∷ᴹ _} ((_ , _ , ()) , _)
              ; {_ ∷ᴹ _ , []ᴹ   } (_ , ())
              ; {_ ∷ᴹ _ , _ ∷ᴹ _} (_ , ()) })
           (rearrV
               { ([]ᴹ , tt)  0  n ; (_ ∷ᴹ _ , tt)   })
              (conseq {Q = λ { []ᴹ  0  n; (_ ∷ᴹ _)   }}
                  { {[]ᴹ    , tt} (_ , 0≡n)  tt , 0≡n , refl
                    ; {_ ∷ᴹ _ , tt} (_ , ()) })
                 skip
                  _  tt)))
           id) ∷ᴺ
        (conseq {Q = λ { []ᴹ  ; (_ ∷ᴹ ss)  suc (length (toList₀ ss))  n }}
            { {[]ᴹ     , []ᴹ    } (_ , ())
              ; {[]ᴹ     , _ ∷ᴹ _ } (_ , ())
              ; {_ ∷ᴹ _  , []ᴹ    } ((_ , _ , ()) , _)
              ; {s ∷ᴹ ss , v ∷ᴹ vs} ((_ , (refl , refl) , ks-s≡kv-v , suc-len-vs≡n) , suc-len-ss≡n) 
                suc-len-vs≡n , trueFromWitness ks-s≡kv-v , refl , tt })
           (rearrS
               { ((s , _) , []ᴹ    )  
                 ; ((s , _) , v ∷ᴹ vs)  ks s  kv v × suc (length (toList₁ vs))  n})
               { (_ , ss)  length (toList₀ ss)  pred n × pred n < n })
              (conseq
                  { {(s , ss) , []ᴹ} ((_ , _ , ()) , _)
                    ; {(s , ss) , v ∷ᴹ vs} ((_ , (ks-s≡kv-v , suc-len-vs≡n) , refl , refl) ,
                                            (_ , (suc-len-ss≡pred-n , pred-n<n) , refl , refl)) 
                      (s , ss) , (refl , refl) , ks-s≡kv-v , suc-len-vs≡n })
                 (rearrV
                     { ((s , _) , (v , vs))  ks s  kv v × suc (length (toList₁ vs))  n })
                    (conseq 
                        { {(s , ss) , (v , vs)} ((ks-s≡kv-v , len-vs≡pred-n) , len-ss≡pred-n , pred-n<n) 
                            (v , vs) , (ks-s≡kv-v , trans (cong suc len-vs≡pred-n) (pred-inverse-lemma pred-n<n)) ,
                            refl , refl })
                       (prod b-t (rec-t {pred n}))
                       (_,_ tt)))
                  { {s' , ss'} ((s , ss) , (len-ss≡pred-n , pred-n<n) , s≡s' , ss≡ss') 
                      trans (cong (length  toList₀) (sym ss≡ss')) len-ss≡pred-n , pred-n<n })))
            { {[]ᴹ} ()
              ; {s ∷ᴹ ss} suc-len-ss≡n 
                  (s , ss) , (cong pred suc-len-ss≡n , pred-lemma suc-len-ss≡n) , refl , refl })) ∷ᴺ •∷ᴬ •∷ᴬ •∷ᴬ []))
     { {[]ᴹ   }  inj₁  (_, (refl , tt))
       ; {_ ∷ᴹ _}  inj₂  inj₁  (_, (refl , refl , tt)) })

keyAlign-finite-expansionR :
  {K : Set} (keq : Decidable (_≡_ {A = K})) (ks : S  K) (kv : V  K) (b : BiGUL F Sᵁ Vᵁ) (c : V  S) 
  TripleR  { (s , v)  ks s  kv v }) b Π 
  (l n : )  n  l  TripleR ((_≡ n)  length  toList₁  proj₂)
                              (expand (suc l) (keyAlignᴮ keq ks kv b c))
                              ((_≡ n)  length  toList₀)
keyAlign-finite-expansionR keq ks kv b c b-t l n n≤l =
  conseq
    (proj₂  proj₁)
    (expandTripleR (keyAlignᴮ keq ks kv b c) (length  toList₁  proj₂) Π  n  (_≡ n)  length  toList₀)
        n rec rec-t 
          conseq
            ((_,_ tt)  proj₁)
            (keyAlign-range keq ks kv b c b-t n rec (conseq (proj₂  proj₁) rec-t id))
            id)
       l n n≤l)
    id