Chuangjie Xu, 2013

Module for both finite and infinite sequences of boolean ₂

\begin{code}

module Sequence where

open import MiniLibrary
open import Inequality

\end{code}

Infinite sequences are defined as functions:

\begin{code}

₂ℕ : Set
₂ℕ =   

 : ₂ℕ
 i = 
 : ₂ℕ
 i = 

\end{code}

Finite sequences are defined as vectros:

\begin{code}

₂Fin :   Set
₂Fin = Vec 

⟨₀⟩ : ₂Fin 1
⟨₀⟩ =   ⟨⟩
⟨₁⟩ : ₂Fin 1
⟨₁⟩ =   ⟨⟩

take : (m : )  ₂ℕ  ₂Fin m
take 0 α = ⟨⟩
take (succ n) α = α 0  take n (α  succ)

drop : (m : )  ₂ℕ  ₂ℕ
drop 0 α = α
drop (succ m) α = drop m (α  succ)

Lemma[drop+] : ∀(n : )  ∀(α : ₂ℕ)  ∀(i : )  drop n α i  α (i + n)
Lemma[drop+] 0        α i = refl
Lemma[drop+] (succ n) α i = Lemma[drop+] n (α  succ) i

isomorphism-₂Fin : ∀(X : Set)  ∀(n : )  (f : ₂Fin (succ n)  X) 
                     \(g :   ₂Fin n  X) 
                     ∀(s : ₂Fin (succ n))  f s  g (head s) (tail s)
isomorphism-₂Fin X n f = ∃-intro g prf
 where
  g :   ₂Fin n  X
  g b s = f (b  s)
  prf : ∀(s : ₂Fin (succ n))  f s  g (head s) (tail s)
  prf (b  s) = refl

max-fin : {n : }  (f : ₂Fin n  ) 
            \(m : )  ∀(s : ₂Fin n)  f s  m
max-fin {0} f = ∃-intro (f ⟨⟩) prf
 where
  prf : ∀(s : ₂Fin 0)  f s  f ⟨⟩
  prf ⟨⟩ = Lemma[n≤n] (f ⟨⟩)
max-fin {succ n} f = ∃-intro m prf
 where
  g :   ₂Fin n  
  g = ∃-witness (isomorphism-₂Fin  n f)
  m₀ : 
  m₀ = ∃-witness (max-fin (g ))
  prf₀ : ∀(s : ₂Fin n)  g  s  m₀
  prf₀ = ∃-elim (max-fin (g ))
  m₁ : 
  m₁ = ∃-witness (max-fin (g ))
  prf₁ : ∀(s : ₂Fin n)  g  s  m₁
  prf₁ = ∃-elim (max-fin (g ))
  m : 
  m = maximum m₀ m₁
  prf : ∀(s : ₂Fin (succ n))  f s  m
  prf (  s) = Lemma[a≤b≤c→a≤c] (prf₀ s) (∧-elim₀ (Lemma[≤-max] m₀ m₁))
  prf (  s) = Lemma[a≤b≤c→a≤c] (prf₁ s) (∧-elim₁ (Lemma[≤-max] m₀ m₁))

\end{code}

Pointwise equality over infinite sequences:

\begin{code}

infixl 10 _≣_

_≣_ : ₂ℕ  ₂ℕ  Set
α  β = ∀(i : )  α i  β i

Lemma[≣-take] : ∀(n : )  ∀(α β : ₂ℕ)  α  β  take n α  take n β
Lemma[≣-take] 0        α β e = refl
Lemma[≣-take] (succ n) α β e = Lemma[Vec-≡] (e 0) (Lemma[≣-take] n (α  succ) (β  succ)  i  e (succ i)))

Lemma[≣-drop] : ∀(n : )  ∀(α β : ₂ℕ)  α  β  drop n α  drop n β
Lemma[≣-drop] 0        α β e = e
Lemma[≣-drop] (succ n) α β e = Lemma[≣-drop] n (α  succ) (β  succ)  i  e (succ i))

\end{code}

"Agree with" relation over infinite sequences, which is an equivalence
relation and a deciable type:

\begin{code}

infixl 10 _≣[_]_

data _≣[_]_ : ₂ℕ    ₂ℕ  Set where
 ≣[zero] : {α β : ₂ℕ}  α ≣[ 0 ] β
 ≣[succ] : {α β : ₂ℕ}{n : }  α ≣[ n ] β  α n  β n  α ≣[ succ n ] β

refl-≣[] : {n : }{α : ₂ℕ}  α ≣[ n ] α
refl-≣[] {0}      = ≣[zero]
refl-≣[] {succ n} = ≣[succ] refl-≣[] refl

sym-≣[] : {n : }{α β : ₂ℕ}  α ≣[ n ] β  β ≣[ n ] α
sym-≣[] {0}      ≣[zero]        = ≣[zero]
sym-≣[] {succ n} (≣[succ] en e) = ≣[succ] (sym-≣[] en) (sym e)

trans-≣[] : {n : }{α₀ α₁ α₂ : ₂ℕ}  α₀ ≣[ n ] α₁  α₁ ≣[ n ] α₂  α₀ ≣[ n ] α₂
trans-≣[] {0}      ≣[zero]        ≣[zero]          = ≣[zero]
trans-≣[] {succ n} (≣[succ] en e) (≣[succ] en' e') = ≣[succ] (trans-≣[] en en') (trans e e')

Lemma[≣[succ]]₀ : {α β : ₂ℕ}{n : }  α ≣[ succ n ] β  α ≣[ n ] β
Lemma[≣[succ]]₀ (≣[succ] en _) = en

Lemma[≣[succ]]₁ : {α β : ₂ℕ}{n : }  α ≣[ succ n ] β  α n  β n
Lemma[≣[succ]]₁ (≣[succ] _ e) = e

Lemma[≣[]-decidable] : {m : }  ∀(α β : ₂ℕ)  decidable (α ≣[ m ] β)
Lemma[≣[]-decidable] {0}      α β = in₀ ≣[zero]
Lemma[≣[]-decidable] {succ m} α β = case claim₀ claim₁ IH
 where
  IH : decidable (α ≣[ m ] β)
  IH = Lemma[≣[]-decidable] {m} α β
  claim₀ : α ≣[ m ] β  decidable (α ≣[ succ m ] β)
  claim₀ em = case c₀ c₁ (₂-discrete (α m) (β m))
   where
    c₀ : α m  β m  decidable (α ≣[ succ m ] β)
    c₀ e = in₀ (≣[succ] em e)
    c₁ : ¬ (α m  β m)  decidable (α ≣[ succ m ] β)
    c₁ f = in₁  e  f (Lemma[≣[succ]]₁ e))
  claim₁ : ¬ (α ≣[ m ] β)  decidable (α ≣[ succ m ] β)
  claim₁ f = in₁  e  f(Lemma[≣[succ]]₀ e))

Lemma[≣[]-zero] : ∀{n : }{α β : ₂ℕ}  α ≣[ succ n ] β  α 0  β 0
Lemma[≣[]-zero] {0}      (≣[succ] ≣[zero] e) = e
Lemma[≣[]-zero] {succ n} (≣[succ] en e)      = Lemma[≣[]-zero] en

Lemma[≣[]-succ] : ∀{n : }{α β : ₂ℕ}  α ≣[ succ n ] β  (α  succ) ≣[ n ] (β  succ)
Lemma[≣[]-succ] {0}      _              = ≣[zero]
Lemma[≣[]-succ] {succ n} (≣[succ] en e) = ≣[succ] (Lemma[≣[]-succ] en) e

\end{code}

The following lemmas give an equivalent defintion of _≣[_]_:

\begin{code}

Lemma[<-≣[]] : ∀{n : }{α β : ₂ℕ}  (∀(i : )  i < n  α i  β i)  α ≣[ n ] β
Lemma[<-≣[]] {0}        {α} {β} f = ≣[zero]
Lemma[<-≣[]] {(succ n)} {α} {β} f = ≣[succ] IH claim
 where
  f' : ∀(i : )  i < n  α i  β i
  f' i r = f i (Lemma[a<b≤c→a<c] r (Lemma[n≤n+1] n))
  IH : α ≣[ n ] β
  IH = Lemma[<-≣[]] {n} {α} {β} f'
  claim : α n  β n
  claim = f n (Lemma[n≤n] (succ n))

Lemma[≣[]-<] : ∀{n : }{α β : ₂ℕ}  α ≣[ n ] β  ∀(i : )  i < n  α i  β i
Lemma[≣[]-<] {0}      _ i        ()
Lemma[≣[]-<] {succ n} e 0        r          = Lemma[≣[]-zero] e
Lemma[≣[]-<] {succ n} e (succ i) (≤-succ r) = Lemma[≣[]-<] (Lemma[≣[]-succ] e) i r

\end{code}

Some useful lemmas about _≣[_]_:

\begin{code}

Lemma[≣[]-≤] : ∀{n m : }{α β : ₂ℕ}  α ≣[ n ] β  m  n  α ≣[ m ] β
Lemma[≣[]-≤] {n} {m} {α} {β} en r = Lemma[<-≣[]] claim₁
 where
  claim₀ : ∀(i : )  i < n  α i  β i
  claim₀ = Lemma[≣[]-<] en
  claim₁ : ∀(i : )  i < m  α i  β i
  claim₁ i r' = claim₀ i (Lemma[a<b≤c→a<c] r' r)

Lemma[≣[]-take] : ∀{n : }{α β : ₂ℕ}  α ≣[ n ] β  take n α  take n β
Lemma[≣[]-take] {0}      {α} {β} _  = refl
Lemma[≣[]-take] {succ n} {α} {β} en = Lemma[Vec-≡] base IH
 where
  base : α 0  β 0
  base = Lemma[≣[]-zero] en
  IH : take n (α  succ)  take n (β  succ)
  IH = Lemma[≣[]-take] (Lemma[≣[]-succ] en)

Lemma[≣[]-drop] : ∀{n m : }{α β : ₂ℕ}  α ≣[ n + m ] β  drop n α ≣[ m ] drop n β
Lemma[≣[]-drop] {n} {0}      {α} {β} _               = ≣[zero]
Lemma[≣[]-drop] {n} {succ m} {α} {β} (≣[succ] enm e) = ≣[succ] IH claim
 where
  IH : drop n α ≣[ m ] drop n β
  IH = Lemma[≣[]-drop] enm
  claim₀ : drop n α m  α (n + m)
  claim₀ = transport {}  k  drop n α m  α k} (Lemma[n+m=m+n] m n) (Lemma[drop+] n α m)
  claim₁ : drop n β m  β (n + m)
  claim₁ = transport {}  k  drop n β m  β k} (Lemma[n+m=m+n] m n) (Lemma[drop+] n β m)
  claim : drop n α m  drop n β m
  claim = trans claim₀ (trans e (sym claim₁))

\end{code}

Concatenation map:

\begin{code}

cons : {m : }  ₂Fin m  ₂ℕ  ₂ℕ
cons ⟨⟩      α i        = α i
cons (h  _) α 0        = h
cons (_  t) α (succ i) = cons t α i

cons₀ : ₂ℕ  ₂ℕ
cons₀ α 0        = 
cons₀ α (succ i) = α i
cons₁ : ₂ℕ  ₂ℕ
cons₁ α 0        = 
cons₁ α (succ i) = α i

Lemma[cons-take-drop] : ∀(n : )  ∀(α : ₂ℕ)  cons (take n α) (drop n α)  α
Lemma[cons-take-drop] 0        α i        = refl
Lemma[cons-take-drop] (succ n) α 0        = refl
Lemma[cons-take-drop] (succ n) α (succ i) = Lemma[cons-take-drop] n (α  succ) i

Lemma[cons-≣] : ∀{m : }  ∀(s : ₂Fin m)  ∀(α β : ₂ℕ)  α  β  cons s α  cons s β
Lemma[cons-≣] ⟨⟩      α β eq i        = eq i
Lemma[cons-≣] (h  _) α β eq 0        = refl
Lemma[cons-≣] (_  t) α β eq (succ i) = Lemma[cons-≣] t α β eq i

Lemma[cons-≣[]] : ∀{n : }  ∀(s : ₂Fin n)  ∀(α β : ₂ℕ)  cons s α ≣[ n ] cons s β
Lemma[cons-≣[]] s α β = Lemma[<-≣[]] (lemma s α β)
 where
  lemma : {n : }(s : ₂Fin n)(α β : ₂ℕ)(i : )  i < n  cons s α i  cons s β i
  lemma ⟨⟩      α β i        ()
  lemma (b  s) α β 0        r          = refl
  lemma (b  s) α β (succ i) (≤-succ r) = lemma s α β i r

Lemma[cons-take-≣[]] : ∀(n : )  ∀(α β : ₂ℕ)  α ≣[ n ] cons (take n α) β
Lemma[cons-take-≣[]] n α β = Lemma[<-≣[]] (lemma n α β)
 where
  lemma : ∀(n : )  ∀(α β : ₂ℕ)  ∀(i : )  i < n  α i  cons (take n α) β i
  lemma 0        α β i        ()
  lemma (succ n) α β 0        r          = refl
  lemma (succ n) α β (succ i) (≤-succ r) = lemma n (α  succ) β i r

Lemma[cons-Vtake-Vdrop] : ∀(n k : )  ∀(s : ₂Fin (n + k))  ∀(α : ₂ℕ) 
                          cons (Vtake n k s) (cons (Vdrop n k s) α)  cons s α
Lemma[cons-Vtake-Vdrop] n 0        s       α i        = refl
Lemma[cons-Vtake-Vdrop] n (succ k) (b  _) α 0        = refl
Lemma[cons-Vtake-Vdrop] n (succ k) (_  s) α (succ i) = Lemma[cons-Vtake-Vdrop] n k s α i

Lemma[cons-Vtake-Vdrop]² : ∀(n m l k : )  (eq : k  m + l) 
                            ∀(s : ₂Fin (k + n))  ∀(α : ₂ℕ) 
    cons (Vtake k n s)
         (cons (Vtake m l (transport {}  x  ₂Fin x} eq (Vdrop k n s)))
               (cons (Vdrop m l ((transport {}  x  ₂Fin x} eq (Vdrop k n s)))) α))
   cons s α
Lemma[cons-Vtake-Vdrop]² n m l k eq s α = goal
 where
  ss : ₂Fin k
  ss = Vdrop k n s
  ss' : ₂Fin (m + l)
  ss' = transport {}  x  ₂Fin x} eq ss
  Q : (i : )  ₂Fin i   Set
  Q i t = cons (Vtake k n s) (cons t α)  cons s α
  claim₀ : cons (Vtake k n s) (cons ss α)  cons s α
  claim₀ = Lemma[cons-Vtake-Vdrop] k n s α
  claim₁ : cons (Vtake k n s) (cons ss' α)  cons s α
  claim₁ = Lemma[transport]  ₂Fin Q k (m + l) eq ss claim₀
  claim₂ : cons (Vtake m l ss') (cons (Vdrop m l ss') α)  cons ss' α
  claim₂ = Lemma[cons-Vtake-Vdrop] m l ss' α
  claim₃ :  cons (Vtake k n s) (cons (Vtake m l ss') (cons (Vdrop m l ss') α))
           cons (Vtake k n s) (cons ss' α)
  claim₃ = Lemma[cons-≣] (Vtake k n s)
                             (cons (Vtake m l ss') (cons (Vdrop m l ss') α))
                             (cons ss' α) claim₂
  goal : cons (Vtake k n s) (cons (Vtake m l ss') (cons (Vdrop m l ss') α))  cons s α
  goal i = trans (claim₃ i) (claim₁ i)

\end{code}

Overwriting map:

\begin{code}

overwrite : ₂ℕ      ₂ℕ
overwrite α 0        b 0        = b
overwrite α 0        b (succ i) = α (succ i)
overwrite α (succ n) b 0        = α 0
overwrite α (succ n) b (succ i) = overwrite (α  succ) n b i

Lemma[overwrite] : ∀(α : ₂ℕ)  ∀(n : )  ∀(b : )  overwrite α n b n  b
Lemma[overwrite] α 0        b = refl
Lemma[overwrite] α (succ n) b = Lemma[overwrite] (α  succ) n b

Lemma[overwrite-≠] : ∀(α : ₂ℕ)  ∀(n : )  ∀(b : )  ∀(i : )  i  n  α i  overwrite α n b i
Lemma[overwrite-≠] α 0        b 0        r = ∅-elim (r refl)
Lemma[overwrite-≠] α 0        b (succ i) r = refl
Lemma[overwrite-≠] α (succ n) b 0        r = refl
Lemma[overwrite-≠] α (succ n) b (succ i) r = Lemma[overwrite-≠] (α  succ) n b i  e  r (ap succ e))

Lemma[overwrite-≣[]] : ∀(α : ₂ℕ)  ∀(n : )  ∀(b : )  α ≣[ n ] overwrite α n b
Lemma[overwrite-≣[]] α n b = Lemma[<-≣[]] claim
 where
  claim : ∀(i : )  i < n  α i  overwrite α n b i
  claim i r = Lemma[overwrite-≠] α n b i (Lemma[m<n→m≠n] r)

\end{code}

The product of a family of deciable sets, indexed by finite sequences,
is also decidable.

\begin{code}

Lemma[₂Fin-decidability] : (P : (n : )  ₂Fin n  Set) 
     (∀(n : )  ∀(s : ₂Fin n)  decidable (P n s)) 
     ∀(n : )  decidable (∀(s : ₂Fin n)  P n s)
Lemma[₂Fin-decidability] P f 0 = cases claim₀ claim₁ (f 0 ⟨⟩)
 where
  claim₀ : P 0 ⟨⟩  ∀(s : ₂Fin 0)  P 0 s
  claim₀ p ⟨⟩ = p
  claim₁ : ¬ (P 0 ⟨⟩)  ¬ (∀(s : ₂Fin 0)  P 0 s)
  claim₁ q g = q (g ⟨⟩)
Lemma[₂Fin-decidability] P f (succ n) = cases claim₀ claim₁ IH
 where
  Q : (m : )  ₂Fin m  Set
  Q m s = P (succ m) (  s)  P (succ m) (  s)
  claim : ∀(m : )  ∀(s : ₂Fin m)  decidable (Q m s)
  claim m s = case sclaim₀ sclaim₁ (f (succ m) (  s))
   where
    sclaim₀ : P (succ m) (  s)  decidable (Q m s)
    sclaim₀ p0s = cases ssclaim₀ ssclaim₁ (f (succ m) (  s))
     where
      ssclaim₀ : P (succ m) (  s)  Q m s
      ssclaim₀ p1s = ∧-intro p0s p1s
      ssclaim₁ : ¬ (P (succ m) (  s))  ¬ (Q m s)
      ssclaim₁ np1s nq = np1s (∧-elim₁ nq)
    sclaim₁ : ¬ (P (succ m) (  s))  decidable (Q m s)
    sclaim₁ np0s = in₁  nq  np0s (∧-elim₀ nq))
  claim₀ : (∀(s : ₂Fin n)  P (succ n) (  s)  P (succ n) (  s)) 
            ∀(s : ₂Fin (succ n))  P (succ n) s
  claim₀ g (  s) = ∧-elim₀ (g s)
  claim₀ g (  s) = ∧-elim₁ (g s)
  claim₁ : ¬ (∀(s : ₂Fin n)  P (succ n) (  s)  P (succ n) (  s)) 
            ¬ (∀(s : ₂Fin (succ n))  P (succ n) s)
  claim₁ h g = h  s  g (  s) , g (  s))
  IH : decidable (∀(s : ₂Fin n)  P (succ n) (  s)  P (succ n) (  s))
  IH = Lemma[₂Fin-decidability] Q claim n

\end{code}